一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

非阻塞模式

 通信小兵 2012-02-22

5.1.1 非阻塞模式

169人閱讀 評論(0) 收藏 舉報

  把套接字設置為非阻塞模式,即通知系統(tǒng)內核:在調用Windows Sockets API時,不要讓線程睡眠,而應該讓函數(shù)立即返回。在返回時,該函數(shù)返回一個錯誤代碼。圖所示,一個非阻塞模式套接字多次調用recv()函數(shù)的過程。前三次調用recv()函數(shù)時,內核數(shù)據(jù)還沒有準備好。因此,該函數(shù)立即返回WSAEWOULDBLOCK錯誤代碼。第四次調用recv()函數(shù)時,數(shù)據(jù)已經(jīng)準備好,被復制到應用程序的緩沖區(qū)中,recv()函數(shù)返回成功指示,應用程序開始處理數(shù)據(jù)。

4274人閱讀 評論(0) 收藏 舉報

  當使用socket()函數(shù)和WSASocket()函數(shù)創(chuàng)建套接字時,默認都是阻塞的。在創(chuàng)建套接字之后,通過調用ioctlsocket()函數(shù),將該套接字設置為非阻塞模式。函數(shù)的第一個參數(shù)是套接字,第二個參數(shù)設置為FIONBIO,第三個參數(shù)設置為unsigned long類型的非零值。下面代碼清單演示了如何用ioctlsocket()函數(shù),設置套接字為非阻塞模式。

SOCKET s; //套接字

unsigned long ul = 1; //設置套接字選項

int nRet; //返回值

s = socket(AF_INET, SOCK_STREAM, 0); //創(chuàng)建套接字

nRet = ioctlsocket(s, FIONBIO, (unsigned long*)&ul); //設置套接字非阻塞模式

if (nRet == SOCKET_ERROR)

{

//設置套接字非阻塞模式,失敗處理

}

套接字設置為非阻塞模式后,在調用Windows Sockets API函數(shù)時,調用函數(shù)會立即返回。大多數(shù)情況下,這些函數(shù)調用都會調用“失敗”,并返回WSAEWOULDBLOCK錯誤代碼。說明請求的操作在調用期間內沒有時間完成。通常,應用程序需要重復調用該函數(shù),直到獲得成功返回代碼。下面程序清單示例了一個在非阻塞套接字上反復調用recv()函數(shù),直到收到1024個字節(jié)的數(shù)據(jù)。

#define NUM_REQUIRED 1024 //需要讀入數(shù)據(jù)的大小

#define MAX_SIZE 2048 //輸入緩沖區(qū)的大小

TCHAR buff[MAX_SIZE]; //輸入緩沖區(qū)

bool close; //對方關閉了連接

SOCKET sock; //Windows sockets

void ReadData(void)

{

int nTotal = 0; //已經(jīng)讀入緩沖區(qū)字節(jié)數(shù)

int nRead = 0; //在調用recv時實際讀入字節(jié)數(shù)

int nLeft = 0; //剩下數(shù)據(jù)的字節(jié)數(shù)

int nBytes = 0; //當前已讀數(shù)據(jù)在緩沖區(qū)的位置

nLeft = NUM_REQUIRED;

while (nTotal != NUM_REQUIRED)//已經(jīng)讀入緩沖區(qū)的字節(jié)數(shù)不等于需要讀入的大小時

{

nRead = recv(sock, &buff[MAX_SIZE - nBytes], nLeft, 0); //接收數(shù)據(jù)

if(SOCKET_ERROR == nRead) //讀操作失敗

{

int err = WSAGetLastError();

if(WSAEWOULDBLOCK == err) //接收數(shù)據(jù)緩沖區(qū)不可用

{

continue; //接著讀取數(shù)據(jù)

}else if(WSAETIMEDOUT == err || WSAENETDOWN == err) //連接已經(jīng)斷開

{

close = TRUE; //函數(shù)退出

break;

}

}

if( 0 == nRead) //客戶端關閉了連接

{

close = TRUE; //函數(shù)退出

break;

}

nTotal += nRead;

nLeft -= nRead;

nBytes += nRead;

}

return;

}

在該程序中,通過調用WSAGetLastError()函數(shù)獲得recv()函數(shù)返回的錯誤代碼。當返回WSAEWOULDBLOCK錯誤時,說明此時套接字的緩沖區(qū)還沒有準備好的數(shù)據(jù)。需要繼續(xù)調用該函數(shù)。

在該程序中,還對recv()函數(shù)返回的其他錯誤代碼進行處理。WSAETIMEDOUTWSAENETDOWN錯誤說明,此時由于網(wǎng)絡系統(tǒng)的原因與對方的連接已經(jīng)斷開了。當函數(shù)返回0時,說明對方關閉了連接。在程序中通過設置close布爾變量值為TRUE,表明與對方的連接已經(jīng)斷開。調用break語句跳出while循環(huán)體,函數(shù)退出。在開發(fā)中,應該根據(jù)具體情況對函數(shù)返回的錯誤值進行具體處理。

不同的Windows Sockets API函數(shù),在調用失敗時返回的WSAEWOULDBLOCK錯誤代碼具有不同的含義。表對幾個Windows Sockets API函數(shù)返回WSAEWOULDBLOCK錯誤的含義進行了總結。

WSAEWOULDBLOCK的含義

函數(shù)名

說明

accept()WSAAcept()

應用程序沒有收到連接請求

recv()、WSARecv()recvfrom()WSARecvfrom()

接收緩沖區(qū)沒有收到數(shù)據(jù)

send()、WSASend()sendfrom()WSASendfrom()

發(fā)送緩沖區(qū)此時不可用

connect()WSAConnect()

連接未能立即完成

closescoket()

通常情況下意味著應用程序使用SO_LINGER選項并且設置了一個非零的超時值,調用了setsocketopt()函數(shù)

需要說明的是并非所有的Windows Sockets API在非阻塞模式下調用,都會返回WSAEWOULDBLOCK錯誤。例如,以非阻塞模式的套接字為參數(shù)調用bind()函數(shù)時,就不會返回該錯誤代碼。當然,在調用WSAStartup()函數(shù)時更不會返回該錯誤代碼,因為該函數(shù)是應用程序第一調用的函數(shù),當然不會返回這樣的錯誤代碼。

要將套接字設置為非阻塞模式,除了使用ioctlsocket()函數(shù)之外,還可以使用WSAAsyncselect()WSAEventselect()函數(shù)。當調用該函數(shù)時,套接字會自動地設置為非阻塞方式。在后續(xù)章節(jié)中,講解該函數(shù)的使用方法。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产色第一区不卡高清| 亚洲国产香蕉视频在线观看| 视频在线免费观看你懂的| 中文字幕av诱惑一区二区| 亚洲精品一区二区三区日韩| 欧美成人免费一级特黄| 国产精品免费福利在线| 国产欧美日韩在线精品一二区| 东京热一二三区在线免| 欧美一级不卡视频在线观看| 两性色午夜天堂免费视频| 美女露小粉嫩91精品久久久| 亚洲欧美日韩中文字幕二欧美| 日本高清二区视频久二区| 麻豆91成人国产在线观看| 亚洲欧洲精品一区二区三区| 国产目拍亚洲精品区一区| 樱井知香黑人一区二区| 中文字字幕在线中文乱码二区| 国产综合欧美日韩在线精品 | 国产又色又爽又黄又大| 亚洲一区二区精品免费| 中文字幕久热精品视频在线| 国产老熟女超碰一区二区三区| 亚洲天堂有码中文字幕视频| 91亚洲精品国产一区| 久草视频这里只是精品| 亚洲一区二区三区福利视频| 婷婷基地五月激情五月| 成人午夜在线视频观看| 国内自拍偷拍福利视频| 九九热视频网在线观看| 老富婆找帅哥按摩抠逼视频| 爱草草在线观看免费视频| 日本精品中文字幕在线视频| 国产午夜福利一区二区| 亚洲五月婷婷中文字幕| 亚洲综合天堂一二三区| 亚洲天堂久久精品成人| 国产精品一区二区三区日韩av| 91精品国自产拍老熟女露脸|