基於事件套接字集合的select 模型

2021-06-05 20:39:27 字數 2895 閱讀 3043

基於事件套接字集合的select 模型

select (選擇)模型是winsock 中最常見的i/o 模型。之所以稱其為「select 模型」,是由於它的「中心思想」便是利用select 函式,實現對i/o 的管理!最初設計該模型時,主要面向的是某些使用unix 作業系統的計算機,它們採用的是berkeley 套接字方案。select 模型已整合到winsock 1.1 中,它使那些想避免在套接字呼叫過程中被無辜「鎖定」的應用程式,採取一種有序的方式,同時進行對多個套接字的管理。

select 模型本質上是一種分類處理思想,預先宣告幾個fd_set(fd_set 結構) 集合,例如readset ,writeset,然後呼叫巨集fd_set(s,&readset) 將關注fd_read 事件的套接字s 新增到readset 集合,呼叫巨集fd_set(s,&writeset)將關注fd_write 事件的套接字s 新增到writeset 集合。其中巨集fd_set(socket s, fd_set set) 將s 新增到set 集合。從根本上說,fd_set 資料型別代表著一系列按關注事件分類的套接字集合。

typedef struct fd_set fd_set;

fd_zero(fd_set *fdset);將指定的檔案描述符集清空,在對檔案描述符集合進行設定前,必須對其進行初始化,如果不清空,由於在系統分配記憶體空間後,通常並不作清空處理,所以結果是不可知的。 

fd_set(fd_set *fdset);用於在檔案描述符集合中增加乙個新的檔案描述符。 

fd_clr(fd_set *fdset);用於在檔案描述符集合中刪除乙個檔案描述符。 

fd_isset(int fd,fd_set *fdset);用於測試指定的檔案描述符是否在該集合中。

然後再呼叫select 函式,對宣告的集合readset 或writeset 進行掃瞄,其函式原型如下:

winsock_api_linkage 

int 

wsaapi

select(

int 

nfds,

fd_set

far* 

readfds,

fd_set

far* 

writefds,

fd_set

far*

exceptfds,

const struct 

timeval

far* 

timeout);

其中,第乙個引數 nfds 會被忽略,一般賦值0 。之所以仍然要提供這個引數,只是為了保持與早期的berkeley套接字應用程式的相容。

其他的三個fd_set 引數,乙個用於檢查可讀性(readfds ),乙個用於檢查可寫性(writefds ),另乙個用於例外資料(exceptfds )。例如我們只關注fd_read事件,則select(0,&readset,null,null,null)。一般來說,這三個fd_set 引數至少有乙個不為null。

呼叫select 會修改每個fd_set 結構,它掃瞄註冊到集合readset 和writeset 中的套接字是否有讀寫事件發生,若有,則對集合進行更新,即將套接字新增到集合readset 和writeset 中。同時,刪除那些不存在待決i/o 操作的套接字控制代碼。select 完成後,會返回在所有fd_set 集合中設定的套接字控制代碼總數。

然後,我們需要遍歷查詢之前註冊到某個集合中的套接字是否仍為其中一部分。這需要呼叫fd_isset(socket s, fd_set set) 來測試套接字是否屬於關注同類事件的套接字集合set 。若是,則對待決的i/o 進行處理。

使用select 模型,可能需要呼叫ioctlsocket 函式將乙個套接字從鎖定模式切換為非鎖定模式。

typedef structdata_packet;

----------------------------------------

void cfiletranssvrview::onstartsvr()

else

::listen(slisten,5);

dword dwthread;

::createthread(null,0,threadselect,(lpvoid)slisten,0,&dwthread);

//::showwindow( hwnd,sw_minimize );

}-----------------------------、

dword winapi cfiletranssvrview::threadselect(lpvoid lpparameter)

else

break;

case 'f': //send file size

requestpath=formatpath(recvpacket.content,recvpacket.length);

recvpacket.length=getfilelength(requestpath);

recvpacket.packettype='f';

::send(fdsocket.fd_array[i],(char*)&recvpacket,

sizeof(recvpacket),0);

break;

case 'd': //send file data

dchnum=recvpacket.length;

requestpath=formatpath(recvpacket.content,recvpacket.length);

sendfile(fdsocket.fd_array[i],dchnum,requestpath);

break;

default:

break;}}

else}}

}}

else

}return 0;

}

基於tcp協議的套接字

簡單版本 一 服務端 import socket 1 買手機 拿到套接字物件,用來鏈結建立鏈結 phone socket.socket socket.af inet,socket.sock stream tcp稱為流式協議sock stream,udp稱為資料報協議sock dgram print ...

基於UDP TCP網路套接字程式設計

傳輸層基於udp的網路通訊流程 客戶端 服務端 1.建立套接字 返回套接字控制代碼 socket 1.建立套接字 返回套接字控制代碼 2.為套接字繫結位址和埠 bind 2.為套接字繫結位址和埠 3.傳送資料 sendto 3.開始接收資料 4.接收資料 recvfrom 4.恢復資料 5.關閉套接...

基於udp的套接字程式設計

客戶端 1 author kelvin2 date 2019 1 30 11 07 3from socket import 4 ip conf 127.0.0.1 8888 5 buffer content 1024 6 udp client socket af inet,sock dgram 資料...