Client向Server send数据,返回WSAEWOULDBLOCK错误
參見MSDN中的一段:
The FD_WRITE network event is handled slightly differently. An FD_WRITE network event is recorded when a socket is first connected with connect/ WSAConnect or accepted with accept/ WSAAccept, and then after a send fails with WSAEWOULDBLOCK and buffer space becomes available. Therefore, an application can assume that sends are possible starting from the first FD_WRITE network event setting and lasting until a send returns WSAEWOULDBLOCK. After such a failure the application will find out that sends are again possible when an FD_WRITE network event is recorded and the associated event object is set.
參考http://blog.csdn.net/strikebone/article/details/1765839這篇文章,如下解釋:
首先,Winsock 異常 WSAEWOULDBLOCK (WSAGetLastError) 的意思是 Output Buffer 已經(jīng)滿了,無法再寫入數(shù)據(jù)。確切的說它其實不算是個錯誤,出現(xiàn)這種異常的絕大部分時候其實都不存在 Output Buffer 已滿情況,而是處于一種“忙”的狀態(tài),而這種“忙”的狀態(tài)還很大程度上是由于接收方造成的。意思就是你要發(fā)送的對象,對方收的沒你發(fā)的快或者對方的接受緩沖區(qū)已被填滿,所以就返回你一個“忙”的標(biāo)志,而這時你再發(fā)多少數(shù)據(jù)都沒任何意義,所以系統(tǒng)就返回 WSAEWOULDBLOCK 異常通知你。
那么,該怎么辦呢?網(wǎng)上有很多朋友的做法是遇到這種情況就 Sleep 一段時間,一般短暫停頓后 Output Buffer 就空出來了,那就又可以繼續(xù)發(fā)送了。推薦的方法:根據(jù) MSDN 文檔所示,當(dāng)出現(xiàn) WSAEWOULDBLOCK 異常后直到空出 Output Buffer 時,系統(tǒng)會發(fā)送一個 FD_WRITE 給發(fā)送方。我們完全可以在等收到 FD_WRITE 消息后再重新發(fā)送從出現(xiàn)異常開始的數(shù)據(jù)包即可(該包需要全部重新發(fā)送)。
至此,該問題結(jié)案。最后順便提一下:FD_WRITE 消息會在至少三鐘情況下出現(xiàn),而上面只是其中的一種,所以我建議給 Socket 做個標(biāo)志判斷以便于規(guī)范性。
客戶端可能的實現(xiàn)如下:
static BOOL ComWrite(PSFTHREAD pSFThread, size_t length, int type, size_t bufsize, void *buf, WCHAR *fname) {BOOL bRet;PSENDLOG_PRIVATE_DATA ses = (PSENDLOG_PRIVATE_DATA)pSFThread->privateData;PSMON_ENV pEnv = pSFThread->pEnv;DWORD dwEvent;WSANETWORKEVENTS nEvents;int nRet;size_t send_size = 0;size_t read_size = 0;HANDLE fd;char *fileBuf = NULL;DWORD fileSize;DWORD rBytes;HANDLE hEvents[] = {GET_EXIT_EVENT(pEnv),ses->socEvent};// Parameter checkif(type >= SFCOM_INPUTTYPE_TAILNUM){return FALSE;}if(bufsize == 0){bufsize = length;}if(type == SFCOM_INPUTTYPE_FILE){fd = CreateFile(fname,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if(fd == INVALID_HANDLE_VALUE){SFERRLOG();return FALSE;}fileSize = GetFileSize(fd, NULL);if(fileSize == -1){goto Cleanup;}else if(fileSize == 0){// File emptygoto Cleanup;}fileBuf = (char*)malloc(fileSize);if(fileBuf == NULL){goto Cleanup;}bRet = ReadFile(fd, fileBuf, fileSize, &rBytes, NULL);if(!bRet || rBytes != fileSize){goto Cleanup;}buf = fileBuf;}size_t length_remained = length;while(1){nRet = send(ses->soc, (char*)buf + send_size, (int)min(length_remained, SFCOM_TCP_SEND_MAX_SIZE), 0);if(nRet == SOCKET_ERROR){if(WSAGetLastError() != WSAEWOULDBLOCK){// ErrorSFCOMDBGOUT("Error occured:%d\n", WSAGetLastError());goto Cleanup;}// WSAEWOULDBLOCK WaitForMultipleObjects FD_WRITESFCOMDBGOUT("ComWrite send WSAEWOULDBLOCK");}else{if(nRet <= length_remained) length_remained -= nRet;send_size += nRet;SFCOMDBGOUT("send %dbytes(total %dbytes)\n", nRet, send_size);if(send_size == length){return TRUE;}else if(send_size < length){continue;}}dwEvent = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);if(dwEvent == WAIT_OBJECT_0){// Exit thread event.ses->exitEventFlag = TRUE;goto Cleanup;}else if(dwEvent == WAIT_OBJECT_0 + 1){// Socket event.nRet = WSAEnumNetworkEvents(ses->soc, ses->socEvent, &nEvents);if(nRet == SOCKET_ERROR){// ErrorSFCOMDBGOUT("ComWrite Error occured:%d\n", WSAGetLastError());goto Cleanup;}if(nEvents.lNetworkEvents & FD_CLOSE){// FD_CLOSESFCOMDBGOUT("ComWrite FD_CLOSE\n");goto Cleanup;}if((nEvents.lNetworkEvents & FD_WRITE) && (nEvents.iErrorCode[FD_WRITE_BIT] == 0)){continue;}else{goto Cleanup;}}else if(dwEvent == WAIT_TIMEOUT){// TimeoutSFCOMDBGOUT("ComWrite WAIT_TIMEOUT\n");goto Cleanup;}else{// ErrorSFCOMDBGOUT("ComWrite WAIT_FAILED\n");goto Cleanup;}}return TRUE;Cleanup:if(type == SFCOM_INPUTTYPE_FILE){CloseHandle(fd);if(fileBuf != NULL){free(fileBuf);}}ComClose(ses);return FALSE; }?
轉(zhuǎn)載于:https://www.cnblogs.com/huangyong9527/archive/2012/06/29/2569650.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Client向Server send数据,返回WSAEWOULDBLOCK错误的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。