導航:首頁 > 編程語言 > socketselect編程

socketselect編程

發布時間:2024-06-10 20:09:24

① 鎬!!!鎬!!!奼傚姪!!鏈夎皝鐭ラ亾鍦⊿OCKET緙栫▼涓,select()鍑芥暟鐨勪綔鐢,鏈濂芥湁浠g爜鐨

Select鍦⊿ocket緙栫▼涓榪樻槸姣旇緝閲嶈佺殑錛屽彲鏄瀵逛簬鍒濆Socket鐨勪漢鏉ヨ撮兘涓嶅お鐖辯敤Select鍐欑▼搴忥紝浠栦滑鍙鏄涔犳儻鍐欒稿俢onnect銆乤ccept銆乺ecv鎴杛ecvfrom榪欐牱鐨勯樆濉炵▼搴忥紙鎵璋撻樆濉炴柟寮廱lock錛岄【鍚嶆濅箟錛屽氨鏄榪涚▼鎴栨槸綰跨▼鎵ц屽埌榪欎簺鍑芥暟鏃跺繀欏葷瓑寰呮煇涓浜嬩歡鐨勫彂鐢燂紝濡傛灉浜嬩歡娌℃湁鍙戠敓錛岃繘紼嬫垨綰跨▼灝辮闃誨烇紝鍑芥暟涓嶈兘絝嬪嵆榪斿洖錛夈傚彲鏄浣跨敤Select灝卞彲浠ュ畬鎴愰潪闃誨烇紙鎵璋撻潪闃誨炴柟寮弉on-block錛屽氨鏄榪涚▼鎴栫嚎紼嬫墽琛屾ゅ嚱鏁版椂涓嶅繀闈炶佺瓑寰呬簨浠剁殑鍙戠敓錛屼竴鏃︽墽琛岃偗瀹氳繑鍥烇紝浠ヨ繑鍥炲肩殑涓嶅悓鏉ュ弽鏄犲嚱鏁扮殑鎵ц屾儏鍐碉紝濡傛灉浜嬩歡鍙戠敓鍒欎笌闃誨炴柟寮忕浉鍚岋紝鑻ヤ簨浠舵病鏈夊彂鐢熷垯榪斿洖涓涓浠g爜鏉ュ憡鐭ヤ簨浠舵湭鍙戠敓錛岃岃繘紼嬫垨綰跨▼緇х畫鎵ц岋紝鎵浠ユ晥鐜囪緝楂橈級鏂瑰紡宸ヤ綔鐨勭▼搴忥紝瀹冭兘澶熺洃瑙嗘垜浠闇瑕佺洃瑙嗙殑鏂囦歡鎻忚堪絎︾殑鍙樺寲鎯呭喌鈥斺旇誨啓鎴栨槸寮傚父銆備笅闈㈣︾粏浠嬬粛涓涓嬶紒

Select鐨勫嚱鏁版牸寮(鎴戞墍璇寸殑鏄疷nix緋葷粺涓嬬殑浼鍏嬪埄socket緙栫▼錛屽拰windows涓嬬殑鏈夊尯鍒錛屼竴浼氬効璇存槑)錛

int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);

鍏堣存槑涓や釜緇撴瀯浣擄細

絎涓錛宻truct fd_set鍙浠ョ悊瑙d負涓涓闆嗗悎錛岃繖涓闆嗗悎涓瀛樻斁鐨勬槸鏂囦歡鎻忚堪絎(file descriptor)錛屽嵆鏂囦歡鍙ユ焺錛岃繖鍙浠ユ槸鎴戜滑鎵璇寸殑鏅閫氭剰涔夌殑鏂囦歡錛屽綋鐒禪nix涓嬩換浣曡懼囥佺¢亾銆丗IFO絳夐兘鏄鏂囦歡褰㈠紡錛屽叏閮ㄥ寘鎷鍦ㄥ唴錛屾墍浠ユ鏃犵枒闂涓涓猻ocket灝辨槸涓涓鏂囦歡錛宻ocket鍙ユ焺灝辨槸涓涓鏂囦歡鎻忚堪絎︺俧d_set闆嗗悎鍙浠ラ氳繃涓浜涘畯鐢變漢涓烘潵鎿嶄綔錛屾瘮濡傛竻絀洪泦鍚團D_ZERO(fd_set *)錛屽皢涓涓緇欏畾鐨勬枃浠舵弿榪扮﹀姞鍏ラ泦鍚堜箣涓璅D_SET(int ,fd_set *)錛屽皢涓涓緇欏畾鐨勬枃浠舵弿榪扮︿粠闆嗗悎涓鍒犻櫎FD_CLR(int ,fd_set*)錛屾鏌ラ泦鍚堜腑鎸囧畾鐨勬枃浠舵弿榪扮︽槸鍚﹀彲浠ヨ誨啓FD_ISSET(int ,fd_set* )銆備竴浼氬効涓句緥璇存槑銆

絎浜岋紝struct timeval鏄涓涓澶у跺父鐢ㄧ殑緇撴瀯錛岀敤鏉ヤ唬琛ㄦ椂闂村礆紝鏈変袱涓鎴愬憳錛屼竴涓鏄縐掓暟錛屽彟涓涓鏄姣縐掓暟銆

鍏蜂綋瑙i噴select鐨勫弬鏁幫細

int maxfdp鏄涓涓鏁存暟鍊礆紝鏄鎸囬泦鍚堜腑鎵鏈夋枃浠舵弿榪扮︾殑鑼冨洿錛屽嵆鎵鏈夋枃浠舵弿榪扮︾殑鏈澶у煎姞1錛屼笉鑳介敊錛佸湪Windows涓榪欎釜鍙傛暟鐨勫兼棤鎵璋擄紝鍙浠ヨ劇疆涓嶆g『銆

fd_set *readfds鏄鎸囧悜fd_set緇撴瀯鐨勬寚閽堬紝榪欎釜闆嗗悎涓搴旇ュ寘鎷鏂囦歡鎻忚堪絎︼紝鎴戜滑鏄瑕佺洃瑙嗚繖浜涙枃浠舵弿榪扮︾殑璇誨彉鍖栫殑錛屽嵆鎴戜滑鍏沖績鏄鍚﹀彲浠ヤ粠榪欎簺鏂囦歡涓璇誨彇鏁版嵁浜嗭紝濡傛灉榪欎釜闆嗗悎涓鏈変竴涓鏂囦歡鍙璇伙紝select灝變細榪斿洖涓涓澶т簬0鐨勫礆紝琛ㄧず鏈夋枃浠跺彲璇伙紝濡傛灉娌℃湁鍙璇葷殑鏂囦歡錛屽垯鏍規嵁timeout鍙傛暟鍐嶅垽鏂鏄鍚﹁秴鏃訛紝鑻ヨ秴鍑簍imeout鐨勬椂闂達紝select榪斿洖0錛岃嫢鍙戠敓閿欒榪斿洖璐熷箋傚彲浠ヤ紶鍏NULL鍊礆紝琛ㄧず涓嶅叧蹇冧換浣曟枃浠剁殑璇誨彉鍖栥

fd_set *writefds鏄鎸囧悜fd_set緇撴瀯鐨勬寚閽堬紝榪欎釜闆嗗悎涓搴旇ュ寘鎷鏂囦歡鎻忚堪絎︼紝鎴戜滑鏄瑕佺洃瑙嗚繖浜涙枃浠舵弿榪扮︾殑鍐欏彉鍖栫殑錛屽嵆鎴戜滑鍏沖績鏄鍚﹀彲浠ュ悜榪欎簺鏂囦歡涓鍐欏叆鏁版嵁浜嗭紝濡傛灉榪欎釜闆嗗悎涓鏈変竴涓鏂囦歡鍙鍐欙紝select灝變細榪斿洖涓涓澶т簬0鐨勫礆紝琛ㄧず鏈夋枃浠跺彲鍐欙紝濡傛灉娌℃湁鍙鍐欑殑鏂囦歡錛屽垯鏍規嵁timeout鍙傛暟鍐嶅垽鏂鏄鍚﹁秴鏃訛紝鑻ヨ秴鍑簍imeout鐨勬椂闂達紝select榪斿洖0錛岃嫢鍙戠敓閿欒榪斿洖璐熷箋傚彲浠ヤ紶鍏NULL鍊礆紝琛ㄧず涓嶅叧蹇冧換浣曟枃浠剁殑鍐欏彉鍖栥

fd_set *errorfds鍚屼笂闈涓や釜鍙傛暟鐨勬剰鍥撅紝鐢ㄦ潵鐩戣嗘枃浠墮敊璇寮傚父銆

struct timeval* timeout鏄痵elect鐨勮秴鏃舵椂闂達紝榪欎釜鍙傛暟鑷沖叧閲嶈侊紝瀹冨彲浠ヤ嬌select澶勪簬涓夌嶇姸鎬侊紝絎涓錛岃嫢灝哊ULL浠ュ艦鍙備紶鍏ワ紝鍗充笉浼犲叆鏃墮棿緇撴瀯錛屽氨鏄灝唖elect緗浜庨樆濉炵姸鎬侊紝涓瀹氱瓑鍒扮洃瑙嗘枃浠舵弿榪扮﹂泦鍚堜腑鏌愪釜鏂囦歡鎻忚堪絎﹀彂鐢熷彉鍖栦負姝錛涚浜岋紝鑻ュ皢鏃墮棿鍊艱句負0縐0姣縐掞紝灝卞彉鎴愪竴涓綰綺圭殑闈為樆濉炲嚱鏁幫紝涓嶇℃枃浠舵弿榪扮︽槸鍚︽湁鍙樺寲錛岄兘絝嬪埢榪斿洖緇х畫鎵ц岋紝鏂囦歡鏃犲彉鍖栬繑鍥0錛屾湁鍙樺寲榪斿洖涓涓姝e礆紱絎涓夛紝timeout鐨勫煎ぇ浜0錛岃繖灝辨槸絳夊緟鐨勮秴鏃舵椂闂達紝鍗硈elect鍦╰imeout鏃墮棿鍐呴樆濉烇紝瓚呮椂鏃墮棿涔嬪唴鏈変簨浠跺埌鏉ュ氨榪斿洖浜嗭紝鍚﹀垯鍦ㄨ秴鏃跺悗涓嶇℃庢牱涓瀹氳繑鍥烇紝榪斿洖鍊煎悓涓婅堪銆

榪斿洖鍊礆細

璐熷礆細select閿欒 姝e礆細鏌愪簺鏂囦歡鍙璇誨啓鎴栧嚭閿 0錛氱瓑寰呰秴鏃訛紝娌℃湁鍙璇誨啓鎴栭敊璇鐨勬枃浠

鍦ㄦ湁浜唖elect鍚庡彲浠ュ啓鍑哄儚鏍風殑緗戠粶紼嬪簭鏉ワ紒涓句釜綆鍗曠殑渚嬪瓙錛屽氨鏄浠庣綉緇滀笂鎺ュ彈鏁版嵁鍐欏叆涓涓鏂囦歡涓銆

渚嬪瓙錛

main()

{

int sock;

FILE *fp;

struct fd_set fds;

struct timeval timeout={3,0}; //select絳夊緟3縐掞紝3縐掕疆璇錛岃侀潪闃誨炲氨緗0

char buffer[256]={0}; //256瀛楄妭鐨勬帴鏀剁紦鍐插尯

/* 鍋囧畾宸茬粡寤虹珛UDP榪炴帴錛屽叿浣撹繃紼嬩笉鍐欙紝綆鍗曪紝褰撶劧TCP涔熷悓鐞嗭紝涓繪満ip鍜宲ort閮藉凡緇忕粰瀹氾紝瑕佸啓鐨勬枃浠跺凡緇忔墦寮

sock=socket(...);

bind(...);

fp=fopen(...); */

while(1)

{

FD_ZERO(&fds); //姣忔″驚鐜閮借佹竻絀洪泦鍚堬紝鍚﹀垯涓嶈兘媯嫻嬫弿榪扮﹀彉鍖

FD_SET(sock,&fds); //娣誨姞鎻忚堪絎

FD_SET(fp,&fds); //鍚屼笂

maxfdp=sock>fp?sock+1:fp+1; //鎻忚堪絎︽渶澶у煎姞1

switch(select(maxfdp,&fds,&fds,NULL,&timeout)) //select浣跨敤

{

case -1: exit(-1);break; //select閿欒錛岄鍑虹▼搴

case 0:break; //鍐嶆¤疆璇

default:

if(FD_ISSET(sock,&fds)) //嫻嬭瘯sock鏄鍚﹀彲璇伙紝鍗蟲槸鍚︾綉緇滀笂鏈夋暟鎹

{

recvfrom(sock,buffer,256,.....);//鎺ュ彈緗戠粶鏁版嵁

if(FD_ISSET(fp,&fds)) //嫻嬭瘯鏂囦歡鏄鍚﹀彲鍐

fwrite(fp,buffer...);//鍐欏叆鏂囦歡

buffer娓呯┖;

}// end if break;

}// end switch

}//end while

}//end main

② SOKET緙栫▼涓涓瀹㈡埛絝榪炴帴澶氫釜鏈嶅姟鍣ㄧ殑闂棰

鍙傝冧笂涓涓鏂規硶銆

涓涓瀹㈡埛絝錛屾垜鍙浠ョ畝鍗曠殑鐞嗚В鎴愪竴涓榪涚▼銆
涓涓榪涚▼鍙浠ュ緢澶氫釜 SOCKET銆
涓涓猄OCKET 鍙浠ヨ繛鎺ヤ竴涓鏈嶅姟鍣錛屽緩絝嬩竴涓榪炴帴銆
鏂版墜錛屽緩璁灝辯敤CSocket鍚э紝 閽堝規瘡涓鏈嶅姟鍣ㄥ疄渚嬪寲涓涓瀵硅薄銆

鑷充簬SOCKET妯″瀷錛屼笉鎬ワ紝絳夊熀鏈鐨勪細浜嗭紝鍐嶆繁鍏ャ

③ c#socket編程怎麼判讀客戶端與伺服器斷開連接

使用Socket類中的Poll方法,就可以。
Socket client //假如已經創建好了,連接到伺服器端得Socket的客戶端對象。
我們只要client.Poll(10,SelectMode.SelectRead)判斷就行了。只要返回True是。就可以認為客戶端已經斷開了。

Poll 方法將會檢查 Socket 的狀態。指定 selectMode 參數的 SelectMode..::.SelectRead,可確定 Socket 是否為可讀。指定 SelectMode..::.SelectWrite,可確定 Socket 是否為可寫。使用 SelectMode..::.SelectError 檢測錯誤條件。Poll 將在指定的時段(以 microseconds 為單位)內阻止執行。如果希望無限期的等待響應,則將 microSeconds 設置為一個負整數。如果要檢查多個套接字的狀態,則不妨使用 Select 方法。

④ Socket編程的幾種模式

其基本原理是:首先建立一個socket連接,然後對其進行操作,比如,從該socket讀數據。因為網路傳輸是要一定的時間的,即使網路通暢的情況下,接受數據的操作也要花費時間。對於一個簡單的單線程程序,接收數據的過程是無法處理其他操作的。比如一個窗口程序,當你接收數據時,點擊按鈕或關閉窗口操作都不會有效。它的缺點顯而易見,一個線程你只能處理一個 socket,用來教課還行,實際使用效果就不行了。select模型 為了處理多個socket連接,聰明的人們發明了select模型。該模型以集合來管理socket連接,每次去查詢集合中的socket狀態,從而達到處理多連接的能力,其函數原型是int select(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout)。比如我們判斷某個socket是否有數據可讀,我們首先將一個fdread集合置空,然後將socket加入到該集合,調用 select(0,&fdread,NULL,NULL,NULL),之後我們判斷socket是否還在fdread中,如果還在,則說明有數據可讀。數據的讀取和阻塞模型相同,調用recv函數。但是每個集合容量都有一個限值,默認情況下是64個,當然你可以重新定義它的大小,但還是有一個最上限,自己設置也不能超過該值,一般情況下是1024。盡管select模型可以處理多連接,但集合的管理多少讓人感到繁瑣。非同步選擇模型 熟悉windows操作系統的都知道,其窗口處理是基於消息的。人們又發明了一種新的網路模型——WSAAsyncSelect模型,即非同步選擇模型。該模型為每個socket綁定一個消息,當socket上出現事先設置的socket事件時,操作系統就會給應用程序發送這個消息,從而對該 socket事件進行處理,其函數原型是int WSAAsynSelect(SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent)。hWnd指明接收消息的句柄,wMsg指定消息ID,lEvent按位設置感興趣的網路事件,入 WSAAsyncSelect(s,hwnd,WM_SOCKET, FD_CONNECT | FD_READ | FD_CLOSE)。該模型的優點是在系統開銷不大的情況下同時處理許多連接,也不需要什麼集合管理。缺點很明顯,即使你的程序不需要窗口,也要專門為 WSAAsyncSelect模型定義一個窗口。另外,讓單個窗口去處理成千上萬的socket操作事件,很可能成為性能瓶頸。事件選擇模型 與WSAAsynSelect模型類似,人們還發明了WSAEventSelect模型,即事件選擇模型。看名字就可以猜測出來,它是基於事件的。WSAAsynSelect模型在出現感興趣的socket事件時,系統會發一個相應的消息。而WSAEventSelect模型在出現感興趣的socket事件時,系統會將相應WSAEVENT事件設為傳信。可能你現在對sokect事件和普通WSAEVENT事件還不是很清楚。 socket事件是與socket操作相關的一些事件,如FD_READ,FD_WRITE,FD_ACCEPT等。而WSAEVENT事件是傳統的事件,該事件有兩種狀態,傳信(signaled)和未傳信(non-signaled)。所謂傳信,就是事件發生了,未傳信就是還沒有發生。我們每次建立一個連接,都為其綁定一個事件,等到該連接變化時,事件就會變為傳信狀態。那麼,誰去接受這個事件變化呢?我們通過一個 WSAWaitForMultipleEvents(...)函數來等待事件發生,傳入參數中的事件數組中,只有有一個事件發生,該函數就會返回(也可以設置為所有事件發生才返回,在這里沒用),返回值為事件的數組序號,這樣我們就知道了哪個事件發生了,也就是該事件對應的socket有了socket操作事件。該模型比起WSAAsynSelect模型的優勢很明顯,不需要窗口。唯一缺點是,該模型每次只能等待64個事件,這一限制使得在處理多 socket時,有必要組織一個線程池,伸縮性不如後面要講的重疊模型。重疊I/O(Overlapped I/O)模型重疊I/O(Overlapped I/O)模型使應用程序達到更佳的系統性能。重疊模型的基本設計原理是讓應用程序使用重疊數據結構,一次投遞一個或多個Winsock I/O請求。重疊模型到底是什麼東西呢?可以與WSAEventSelect模型做類比(其實不恰當,後面再說),事件選擇模型為每個socket連接綁定了一個事件,而重疊模型為每個socket連接綁定了一個重疊。當連接上發生socket事件時,對應的重疊就會被更新。其實重疊的高明之處在於,它在更新重疊的同時,還把網路數據傳到了實現指定的緩存區中。我們知道,前面的網路模型都要用戶自己通過recv函數來接受數據,這樣就降低了效率。我們打個比方,WSAEventSelect模型就像郵局的包裹通知,用戶收到通知後要自己去郵局取包裹。而重疊模型就像送貨上門,郵遞員發給你通知時,也把包裹放到了你事先指定的倉庫中。 重疊模型又分為事件通知和完成常式兩種模式。在分析這兩種模式之前,我們還是來看看重疊數據結構: typedef struct WSAOVERLAPPED{DWORD Internal; DWORD InternalHigh; DWORD Offset; DWORD OffsetHigh; WSAEVENT hEvent; }WSAOVERLAPPED, FAR * LPWSAOVERLAPPED; 該數據結構中,Internal、InternalHigh、Offset、OffsetHigh都是系統使用的,用戶不用去管,唯一關注的就是 hEvent。如果使用事件通知模式,那麼hEvent就指向相應的事件句柄。如果是完成常式模式,hEvent設為NULL。我們現在來看事件通知模式,首先創建一個事件hEvent,並創建一個重疊結構AcceptOverlapped,並設置AcceptOverlapped.hEvent = hEvent,DataBuf是我們事先設置的數據緩存區。調用 WSARecv(AcceptSocket,&DataBuf,1,&RecvBytes,&Flags,&AcceptOverlapped,NULL),則將AcceptSocket與AcceptOverlapped重疊綁定在了一起。當接收到數據以後,hEvent就會設為傳信,而數據就會放到 DataBuf中。我們再通過WSAWaitForMultipleEvents(...)接收到該事件通知。這里我們要注意,既然是基於事件通知的,那它就有一個事件處理上限,一般為64。 完成常式和事件通知模式的區別在於,當相應的socket事件出現時,系統會調用用戶事先指定的回調函數,而不是設置事件。其實就是將WSARecv的最後一個參數設為函數指針。該回調函數的原型如下: void CALLBACK CompletionROUTINE( DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags);其中,cbTransferred表示傳輸的位元組數,lpOverlapped是發生socket事件的重疊指針。我們調用 WSARecv(AcceptSocket,&DataBuf,1,&RecvBytes,&Flags,&AcceptOverlapped,WorkerRoutine) 將AcceptSocket與WorkRoutine常式綁定。這里有一點小提示,當我們創建多個socket的連接時,最好把重疊與相應的數據緩存區用一個大的數據結構放到一塊,這樣,我們在常式中通過lpOverlapped指針就可以直接找到相應的數據緩存區。這里要注意,不能將多個重疊使用同一個數據緩存區,這樣在多個重疊都在處理時,就會出現數據混亂。完成埠模型 下面我們來介紹專門用於處理為數眾多socket連接的網路模型——完成埠。因為需要做出大量的工作以便將socket添加到一個完成埠,而其他方法的初始化步驟則省事多了,所以對新手來說,完成埠模型好像過於復雜了。然而,一旦弄明白是怎麼回事,就會發現步驟其實並非那麼復雜。所謂完成埠,實際是Windows採用的一種I/O構造機制,除套接字句柄之外,還可以接受其他東西。使用這種模式之前,首先要創建一個I/O完成埠對象,該函數定義如下: HANDLE CreateIoCompletionPort( HANDLE FileHandle, HANDLE ExistingCompletionPort, DWORD CompletionKey, DWORD NumberOfConcurrentThreads);該函數用於兩個截然不同的目的:1)用於創建一個完成埠對象。2)將一個句柄同完成埠關聯到一起。 通過參數NumberOfConcurrentThreads,我們可以指定同時運行的線程數。理想狀態下,我們希望每個處理器各自負責一個線程的運行,為完成埠提供服務,避免過於頻繁的線程任務切換。對於一個socket連接,我們通過 CreateIoCompletionPort((HANDLE)Accept,CompletionPort, (DWORD)PerHandleData,0)將Accept連接與CompletionPort完成埠綁定到一起,CompetionPort對應的那些線程不斷通過GetQueuedCompletionStatus來查詢與其關聯的socket連接是否有I/O操作完成,如果有,則做相應的數據處理,然後通過WSARecv將該socket連接再次投遞,繼續工作。完成埠在性能和伸縮性方面表現都很好,相關聯的socket連接數目沒有限制。

閱讀全文

與socketselect編程相關的資料

熱點內容
5g影視為什麼不能觀看了 瀏覽:662
韓國張美仁愛三部曲 瀏覽:540
安卓版手機怎麼拍照 瀏覽:950
如何解鎖文件夾鎖 瀏覽:720
免費在線觀看的網路電視劇 瀏覽:591
svn命令查看地址 瀏覽:896
丁度巴拉度所有作品 瀏覽:103
手機在線免費觀看推理片 瀏覽:150
黑科技app免費看視頻 瀏覽:265
數控里編譯程序公式 瀏覽:635
安卓系統趣步糖果怎麼賣 瀏覽:850
捷徑怎麼打開app內部 瀏覽:363
轉pdf出錯 瀏覽:81
vip影院電視劇免費觀看 瀏覽:840
伺服器如何更改只讀文件 瀏覽:870
聖安地列斯文件夾圖片 瀏覽:890
韓國在線觀看 瀏覽:904
為啥解壓不了winrar 瀏覽:703
android線程通訊 瀏覽:613
vf退出的命令 瀏覽:611