static int AsynSelectLoop(void) { size_t index; int nready; WSAEVENT hEvent; SOCKET sockfd; WSANETWORKEVENTS event_struct; if (g_count == 0) { Sleep(10); return 0; } nready = WSAWaitForMultipleEvents(g_count, g_events, FALSE, 100, FALSE); if (nready == WSA_WAIT_FAILED) { fprintf(stderr, ("WSAWaitForMultipleEvents() failed, %s"), LAST_ERROR_MSG); return -1; } else if (nready == WSA_WAIT_TIMEOUT) { } else if (nready == WSA_WAIT_IO_COMPLETION) { } else { index = WSA_WAIT_EVENT_0 + nready; if (index >= WSA_MAXIMUM_WAIT_EVENTS) { fprintf(stderr, "invalid event index: %d.\n", index); return -2; } sockfd = g_connections[index]; hEvent = g_events[index]; if (WSAEnumNetworkEvents(sockfd, hEvent, &event_struct) == SOCKET_ERROR) { fprintf(stderr, ("WSAEnumNetworkEvents() failed, %s"), LAST_ERROR_MSG); OnClose(sockfd, index, 0); return -3; } HandleEvents(sockfd, index, &event_struct); } return 0; }
// // This is the wait function used to keep track of events // int DoWait(WSAEVENT *Handles, Socklist *socklist) { DWORD wait_rc = 0; WSAEVENT hTemp = WSA_INVALID_EVENT; Socklist socklTemp; int i = 0; // // Rotate the array, beginning at index 1, by one element. // This ensures that all handles get a fair chance to be serviced. // // There is no way to detect how many handles were signalled when // WSAWaitForMultipleObjects() returns. We simply pick the first one and // come back to this function later // Without the rotation below, this has the potential for starving // connections accepted later. // // Index 0 is avoided, since it is our listening socket. // for ( i = 1; i < curr_size-1; i++ ) { hTemp = Handles[i+1]; Handles[i+1] = Handles[i]; Handles[i] = hTemp; socklTemp = socklist[i+1]; socklist[i+1] = socklist[i]; socklist[i] = socklTemp; } if(WSA_WAIT_FAILED == (wait_rc = WSAWaitForMultipleEvents(curr_size, Handles, FALSE, WSA_INFINITE, FALSE ))) { ERR("WSAWaitForMultipleEvents()"); return -1; } return(wait_rc - WSA_WAIT_EVENT_0); }
/*------------------------------------------------------------------------------------------------------------------ -- FUNCTION: TimerThread -- -- DATE: Febuary 6th, 2016 -- -- REVISIONS: -- -- DESIGNER: Ruoqi Jia -- -- PROGRAMMER: Ruoqi Jia -- -- INTERFACE: DWORD WINAPI TimerThread(LPVOID lpParameter) -- -- RETURNS: void -- -- NOTES: Sets a timer for the UDP thread. If a packet didnt arrive in the given time it will timeout and close the -- socket. It is used for when packets are dropped due to the nature of UDP and we need to determine if there -- are anymore incoming traffics coming in to determine the end of transmission. --------------------------------------------------------------------------------------------------------------------*/ DWORD WINAPI TimerThread(LPVOID lpParameter) { LPSOCKET_INFORMATION SOCKET_INFO; WSAEVENT e[1]; e[0] = TimerEvent; SOCKET_INFO = (LPSOCKET_INFORMATION)lpParameter; while (TRUE) { if (WSAWaitForMultipleEvents(1, e, FALSE, 100, FALSE) == WSA_WAIT_TIMEOUT) { EndOfTransmission = TRUE; WSACloseEvent(e[0]); return FALSE; } WSAResetEvent(e[0]); } return TRUE; }
DWORD mono_win32_wsa_wait_for_multiple_events (DWORD count, const WSAEVENT FAR *handles, BOOL waitAll, DWORD timeout, BOOL alertable) { DWORD result = WAIT_FAILED; MonoThreadInfo * const info = alertable ? mono_thread_info_current_unchecked () : NULL; if (info) enter_alertable_wait (info); result = WSAWaitForMultipleEvents (count, handles, waitAll, timeout, alertable); // NOTE, leave_alertable_wait should not affect GetLastError but // if changed, GetLastError needs to be preserved and reset before returning. if (info) leave_alertable_wait (info); return result; }
int tube_wait(struct tube* tube) { /* block on eventhandle */ DWORD res = WSAWaitForMultipleEvents( 1 /* one event in array */, &tube->event /* the event to wait for, our pipe signal */, 0 /* wait for all events is false */, WSA_INFINITE /* wait, no timeout */, 0 /* we are not alertable for IO completion routines */ ); if(res == WSA_WAIT_TIMEOUT) { return 0; } if(res == WSA_WAIT_IO_COMPLETION) { /* a bit unexpected, since we were not alertable */ return 0; } return 1; }
void EventTCPSocket::loop( HANDLE stopEvent, uint32_t idleTimeout, uint32_t closeTimeout ) { if ( mSocket == INVALID_SOCKET ) EXCEPT( L"Cannot loop, invalid socket" ); WSAEVENT events[2] = { (WSAEVENT)stopEvent, mNetworkEvent }; while ( mState != State_Closed ) { DWORD wait = ( idleTimeout > 0 ? idleTimeout : WSA_INFINITE ); if ( mState == State_Closing ) wait = closeTimeout; DWORD event = WSAWaitForMultipleEvents( 2, events, FALSE, wait, FALSE ); switch ( event ) { case WSA_WAIT_FAILED: EXCEPT_WSA( L"Socket event wait failed" ); break; case WSA_WAIT_TIMEOUT: if ( mState == State_Closing ) { mCloseReason = Close_Unexpected; close(); } else { for ( SocketListener* listener : mListeners ) if ( listener->idleCallback( this ) ) break; } break; case WSA_WAIT_EVENT_0: closeRequest(); break; case WSA_WAIT_EVENT_0 + 1: process(); break; } } }
int O2Agent:: connect2(SOCKET s, const struct sockaddr *name, int namelen, int timeout) { bool err = false; WSAEVENT event = WSACreateEvent(); if (event == WSA_INVALID_EVENT) err = true; if (!err && WSAEventSelect(s, event, FD_CONNECT) == SOCKET_ERROR) err = true; if (!err && connect(s, name, namelen) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) err = true; //非ブロッキングでconnectした場合、通常はSOCKET_ERRORになり //WSAGetLastError() == WSAEWOULDBLOCKが返ってくる。 //それ以外のエラーは本当にconnect失敗 } else err = true; if (!err && WSAWaitForMultipleEvents(1, &event, FALSE, timeout, FALSE) != WSA_WAIT_EVENT_0) err = true; WSANETWORKEVENTS events; if (!err && WSAEnumNetworkEvents(s, event, &events) == SOCKET_ERROR) err = true; if (!err && (!(events.lNetworkEvents & FD_CONNECT) || events.iErrorCode[FD_CONNECT_BIT] != 0)) err = true; WSAEventSelect(s, NULL, 0); WSACloseEvent(event); /* back to blocking mode ulong argp = 0; ioctlsocket(s, FIONBIO, &argp); */ return (err ? SOCKET_ERROR : 0); }
UDPPacket *UDPSocket::poll() { if (WSAWaitForMultipleEvents(1, &event, false, 0, true) == WSA_WAIT_EVENT_0) { int len, FromLen = sizeof(INADDR); INADDR src; len = recvfrom(sid, packet.msg, PACKET_MAX_LENGTH, 0, src.getAddress(), &FromLen); if (len <= 0) return NULL; packet.src = src; packet.len = len; return &packet; } return NULL; }
int32_t OsNetworkReceiveFrom(THandle aHandle, uint8_t* aBuffer, uint32_t aBytes, TIpAddress* aAddress, uint16_t* aPort) { int32_t received; OsNetworkHandle* handle = (OsNetworkHandle*)aHandle; struct sockaddr_in addr; int len = sizeof(addr); WSAEVENT event; HANDLE handles[2]; DWORD ret; if (SocketInterrupted(handle)) { return -1; } sockaddrFromEndpoint(&addr, 0, 0); event = WSACreateEvent(); if (NULL == event) { return -1; } if (0 != WSAEventSelect(handle->iSocket, event, FD_READ|FD_CLOSE)) { WSACloseEvent(event); return -1; } received = recvfrom(handle->iSocket, (char*)aBuffer, aBytes, 0, (struct sockaddr*)&addr, &len); if (SOCKET_ERROR==received && WSAEWOULDBLOCK==WSAGetLastError()) { handles[0] = event; handles[1] = handle->iEvent; ret = WSAWaitForMultipleEvents(2, &handles[0], FALSE, INFINITE, FALSE); if (WAIT_OBJECT_0 == ret) { received = recvfrom(handle->iSocket, (char*)aBuffer, aBytes, 0, (struct sockaddr*)&addr, &len); } } SetSocketBlocking(handle->iSocket); WSACloseEvent(event); *aAddress = addr.sin_addr.s_addr; *aPort = SwapEndian16(addr.sin_port); return received; }
DWORD interfaceChangeThread(LPVOID aArg) { InterfaceChangeObserver* obs = (InterfaceChangeObserver*)aArg; while (obs->iShutdown == 0) { DWORD ret = WAIT_FAILED; DWORD bytes; if (SOCKET_ERROR == WSAIoctl(obs->iSocket, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &bytes, NULL, NULL) && WSAEWOULDBLOCK == WSAGetLastError()) { HANDLE handles[2]; handles[0] = obs->iEvent; handles[1] = obs->iShutdownEvent; ret = WSAWaitForMultipleEvents(2, &handles[0], FALSE, INFINITE, FALSE); } if (WAIT_OBJECT_0 == ret) { (obs->iCallback)(obs->iArg); (void)WSAResetEvent(obs->iEvent); } } (void)ReleaseSemaphore(obs->iSem, 1, NULL); return 0; }
/*------------------------------------------------------------------------------------------------------------------ -- FUNCTION: ServerRoutine -- DATE: 14/04/16 -- REVISIONS: (V1.0) -- DESIGNER: Martin Minkov -- PROGRAMMER: Martin Minkov -- INTERFACE: void CALLBACK ServerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags) -- -- -- RETURNS: VOID -- NOTES: The completion routine used for UDP receiving. Constantly pushes valid data received into the circ buff so it can be used to play audio later. ----------------------------------------------------------------------------------------------------------------------*/ void CALLBACK ServerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags) { DWORD RecvBytes = 0, Index; DWORD Flags = 0; WSAEVENT EventArray[1] = { 0 }; WSAEVENT acceptEvent; // Reference the WSAOVERLAPPED structure as a SOCKET_INFORMATION structure LPSOCKET_INFORMATION SOCKINFO = (LPSOCKET_INFORMATION)Overlapped; initSockInfo(SOCKINFO, SOCKINFO->Buffer, SOCKINFO->server); if (Error != 0) { qDebug() << "I/O operation failed with value" + Error; printf("%d", Error); fflush(stdout); GlobalFree(SOCKINFO); SetEvent(streamStop); return; } if ((acceptEvent = WSACreateEvent()) == WSA_INVALID_EVENT) { qDebug() <<"WSACreateEvent() failed"; GlobalFree(SOCKINFO); return; } Index = WSAWaitForMultipleEvents(1, EventArray, FALSE, 10000000, TRUE); if (Index == WSA_WAIT_TIMEOUT) { qDebug() <<"Timeout in UDP Server"; GlobalFree(SOCKINFO); return; } receiveUDP(SOCKINFO, streamServer, BytesTransferred, Flags); cData.push(SOCKINFO->Buffer, 60000); }
int poll(struct pollfd *pollfds, nfds_t nfds, int timeout) { SOCKET *fds; HANDLE *hEvents; DWORD n; fds = (SOCKET *)alloca(sizeof(SOCKET) * nfds); hEvents = (HANDLE *)alloca(sizeof(HANDLE) * nfds); if (init(pollfds, nfds, fds, hEvents) < 0) { clean(nfds, fds, hEvents); return -1; } n = WSAWaitForMultipleEvents(nfds, hEvents, FALSE, timeout, FALSE); if (n == WSA_WAIT_FAILED) { clean(nfds, fds, hEvents); return -1; } else if (n == WSA_WAIT_TIMEOUT) { clean(nfds, fds, hEvents); return 0; } else { SOCKET fd; HANDLE hEvent; WSANETWORKEVENTS events; n -= WSA_WAIT_EVENT_0; fd = fds[n]; hEvent = hEvents[n]; if (WSAEnumNetworkEvents(fd, hEvent, &events) < 0) { clean(nfds, fds, hEvents); return -1; } pollfds[n].revents = (short) events.lNetworkEvents; clean(nfds, fds, hEvents); return n + 1; } }
static DirectResult WaitForData( VoodooLink *link, int timeout_ms ) { Link *l = link->priv; DWORD wait_result; WSAEventSelect( l->socket, l->event, FD_READ ); wait_result = WSAWaitForMultipleEvents( 1, &l->event, FALSE, timeout_ms, FALSE ); switch (wait_result) { case WSA_WAIT_EVENT_0: return DR_OK; case WSA_WAIT_TIMEOUT: return DR_TIMEOUT; default: D_ERROR( "Voodoo/Link: WaitForMultipleObjects() failed!\n" ); } return DR_FAILURE; }
DWORD HXWSAEventWaiter::HelperThread::Live() { while(1) { /* * Wait until it is time to start waiting. */ WaitForSingleObjectEx(m_hGoAheadAndWait, INFINITE, FALSE); /* * Are we supposed to be exiting? */ if(m_bPleaseDieNow) { return 0; } /* * Wait on what we are supposed to wait on. */ m_dwRetVal = WSAWaitForMultipleEvents(m_dwNumEvents, m_pEvents, FALSE, m_dwTimeout, FALSE); /* * Reset our state for waiting again. */ ResetEvent(m_hGoAheadAndWait); /* * Raise our hand and say we are done. */ SetEvent(m_hIAmDone); } return 0; }
void ListenerImpl::doListen() { HANDLE hWaits[2]; hWaits[0] = hKillEvent; hWaits[1] = hSocketEvent; WSANETWORKEVENTS events; while(true) { // Wait for either the kill event or an accept event : DWORD dwRet = WSAWaitForMultipleEvents(2, hWaits, FALSE, INFINITE, FALSE); //If kill event then quit loop : if (dwRet == WAIT_OBJECT_0) { break; } int nRet = WSAEnumNetworkEvents(hSocket, hSocketEvent, &events); if (nRet == SOCKET_ERROR) { //Error break; } //Deal with the new incoming connection if ((events.lNetworkEvents & FD_ACCEPT) && (events.iErrorCode[FD_ACCEPT_BIT] == 0)) { if(!acceptConnectionRequest()) break; } else break; } }
//////////////////////////////////////////////////////////////////////////////// // 函数名:INT RecvFrom( // SOCKET hSocket, // struct sockaddr * pFrom, // INT nFromlen, // CHAR *pszBuffer, // INT nBufferSize, // DWORD dwTimeout ) // 用 途:接收数据报 // 对全局变量的影响:无 // 参 数: // hSocket : 套接字 // pFrom : 数据报的源地址 // nFromlen : 地址长度 // pszBuffer : 数据缓冲区 // nBufferSize : 缓冲区大小 // dwTimeout : 超时 // 返回值:INT //////////////////////////////////////////////////////////////////////////////// INT CBufSocket::RecvFrom(SOCKET hSocket, struct sockaddr * pFrom, INT nFromlen,CHAR *pszBuffer, INT nBufferSize, DWORD dwTimeout) { HANDLE hReadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hReadEvent == NULL) { SetLastError((INT)GetLastError() ); return (SOCKET_ERROR); } DWORD dwRecvBytes = 0, dwFlags = 0; WSABUF WSABuff; ZeroMemory(&WSABuff,sizeof(WSABUF)); WSABuff.len = nBufferSize; WSABuff.buf = pszBuffer; for (;;) { // 注册FD_READ事件 if( WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, FD_READ) == SOCKET_ERROR) { CloseHandle(hReadEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hReadEvent, TRUE, dwTimeout, TRUE); if( dwWaitResult != WSA_WAIT_EVENT_0 ) { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); SetLastError( WSAGetLastError()); return (SOCKET_FAIL); } ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hReadEvent,&NetEvent) == SOCKET_ERROR) { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } if(NetEvent.iErrorCode[FD_READ_BIT] !=0 ) // 发生错误 { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); SetLastError(NetEvent.iErrorCode[FD_READ_BIT]); return (SOCKET_FAIL); } //////////////////////////////////////////////////////////////// // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); INT nAddrLen = nFromlen; if ( WSARecvFrom(hSocket, &WSABuff, 1, &dwRecvBytes, &dwFlags,pFrom, &nAddrLen, NULL, NULL) == SOCKET_SUCCESS ) break; if ( WSAGetLastError() != WSAEWOULDBLOCK) { CloseHandle(hReadEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } /////////////////////////////////////////////////////////////////////////// // 睡眠一段时间 ////////////////////////////////////////////////////////////////////////// Sleep(DEFAULT_BLOCKED_SNDRCV_SLEEP); } CloseHandle(hReadEvent); return ((INT) dwRecvBytes); }
//////////////////////////////////////////////////////////////////////////////// // 函数名:SOCKET Accept( // struct sockaddr * pSocketAddr, // LPINT nAddrLen, // HANDLE hEndEvent, // DWORD dwTimeout /*= DEFAULT_ACCEPT_TIMEOUT*/ ) // 用 途:接受套接字连接(允许中断) // 对全局变量的影响:无 // 参 数: // pSocketAddr : SOCKET地址 // nAddrLen : 地址长度 // hEndEvent : 结束监听事件 // dwTimeout : 超时 // 返回值:SOCKET //////////////////////////////////////////////////////////////////////////////// SOCKET CBufSocket::Accept(struct sockaddr * pSocketAddr, LPINT nAddrLen,HANDLE hEndEvent,DWORD dwTimeout /*= DEFAULT_ACCEPT_TIMEOUT*/) { if( hEndEvent == NULL) return Accept(pSocketAddr,nAddrLen,dwTimeout); HANDLE hAcceptEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hAcceptEvent == NULL) { SetLastError( (INT)GetLastError() ); return (INVALID_SOCKET); } WSAEVENT hEvent[2]; hEvent[0] = (WSAEVENT)hAcceptEvent; hEvent[1] = (WSAEVENT)hEndEvent; // 注册FD_ACCEPT事件 if( WSAEventSelect(m_hSocket, (WSAEVENT) hAcceptEvent, FD_ACCEPT) == SOCKET_ERROR) { CloseHandle(hAcceptEvent); SetLastError( WSAGetLastError() ); return (INVALID_SOCKET); } SOCKET hSocketAccept = WSAAccept(m_hSocket, pSocketAddr, nAddrLen, NULL, 0); INT nConnectError = WSAGetLastError(); if ((hSocketAccept == INVALID_SOCKET) && (nConnectError == WSAEWOULDBLOCK)) { // 阻塞 DWORD dwWaitResult = WSAWaitForMultipleEvents(2, hEvent, FALSE,dwTimeout, TRUE); if (dwWaitResult == WSA_WAIT_EVENT_0) { ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(m_hSocket,hAcceptEvent,&NetEvent) == SOCKET_ERROR) SetLastError( WSAGetLastError() ); else if(NetEvent.iErrorCode[FD_ACCEPT_BIT] !=0 ) // 发生错误 SetLastError( NetEvent.iErrorCode[FD_ACCEPT_BIT] ); else hSocketAccept = WSAAccept(m_hSocket, pSocketAddr, nAddrLen, NULL, 0); } else SetLastError( WSAGetLastError() ); } // 注销网络事件 WSAEventSelect(m_hSocket, (WSAEVENT) hAcceptEvent, 0); CloseHandle(hAcceptEvent); if (hSocketAccept != INVALID_SOCKET) { // 设置套接字的属性为地址可重用并且为非阻塞的 if ( !Block(hSocketAccept, 0) || !SetSocketOption(hSocketAccept) ) { closesocket(hSocketAccept); return (INVALID_SOCKET); } } return (hSocketAccept); }
// 接收数据 bool CCommunication::PendingReceive(DWORD dwlen) { ZeroMemory(m_pbBuffer, m_nBufferSize); WSABUF wsabuf; WSAOVERLAPPED over; DWORD dwRecv = 0; DWORD dwTotalRecv = 0; DWORD dwFlags; DWORD dwRet; BOOL fPending; int nRet; ZeroMemory(&over, sizeof(WSAOVERLAPPED)); wsabuf.buf = m_pbBuffer; wsabuf.len = dwlen; over.hEvent = WSACreateEvent(); if(over.hEvent == WSA_INVALID_EVENT) { CloseSocket(); return false; } while(1) { dwFlags = 0; fPending = FALSE; // 接收数据 nRet = WSARecv(m_WorkSocket, &wsabuf, 1, &dwRecv, &dwFlags, &over, NULL); if(nRet != 0) { if( WSAGetLastError() != WSA_IO_PENDING) { WSACloseEvent(over.hEvent); CloseSocket(); return false; } else { fPending = TRUE; } } else { fPending = TRUE; } // 接收I/O未结束 if(fPending) { // 等待接收I/O操作完成 dwRet = WSAWaitForMultipleEvents(1, &(over.hEvent), FALSE, m_nTimeOut*1000, FALSE); if(dwRet==WSA_WAIT_FAILED || dwRet==WAIT_TIMEOUT) { WSACloseEvent(over.hEvent); CloseSocket(); return false; } WSAResetEvent(over.hEvent); // 判断重叠操作是否成功 if(!WSAGetOverlappedResult(m_WorkSocket, &over, &dwRecv, FALSE, &dwFlags)) { WSACloseEvent(over.hEvent); CloseSocket(); return false; } else { if(dwRecv == 0) { WSACloseEvent(over.hEvent); CloseSocket(); return false; } // 计算接收总字节数 dwTotalRecv += dwRecv; wsabuf.len -= dwRecv; if(wsabuf.len <= 0) { break; } else { wsabuf.buf += dwRecv; } } } }//while(1) 接收未结束 if(over.hEvent) { WSACloseEvent(over.hEvent); } return true; }
// 发送数据 bool CCommunication::PendingSend(DWORD dwlen) { WSABUF wsabuf; WSAOVERLAPPED over; DWORD dwSend; DWORD dwTotalSend = 0; DWORD dwFlags; DWORD dwRet; BOOL fPending; ZeroMemory(&over, sizeof(WSAOVERLAPPED)); wsabuf.buf = m_pbBuffer; wsabuf.len = dwlen; over.hEvent = WSACreateEvent(); if (over.hEvent == WSA_INVALID_EVENT) { #ifdef _ZZYDEBUG GC_TRACE("Error5"); #endif CloseSocket(); return false; } while(1) { fPending = FALSE; // 发送数据 int nRet = WSASend(m_WorkSocket, &wsabuf, 1, &dwSend, 0, &over, NULL); if (nRet != 0) { if (WSAGetLastError() != WSA_IO_PENDING) { #ifdef _ZZYDEBUG GC_TRACE("Error4:%d",WSAGetLastError()); #endif WSACloseEvent(over.hEvent); CloseSocket(); return false; } else { fPending = TRUE; } } else { fPending = TRUE; } // 发送I/O操作未结束 if (fPending) { // 等待发送I/O操作接束 dwRet = WSAWaitForMultipleEvents(1, &(over.hEvent), FALSE, m_nTimeOut*1000, FALSE); if (dwRet==WSA_WAIT_FAILED || dwRet==WAIT_TIMEOUT) { #ifdef _ZZYDEBUG if (dwRet==WSA_WAIT_FAILED) GC_TRACE("Error1"); else GC_TRACE("Error6"); #endif WSACloseEvent(over.hEvent); CloseSocket(); return false; } WSAResetEvent(over.hEvent); // 判断重叠操作是否成功 if (!WSAGetOverlappedResult(m_WorkSocket, &over, &dwSend, FALSE, &dwFlags)) { #ifdef _ZZYDEBUG GC_TRACE("Error2"); #endif WSACloseEvent(over.hEvent); CloseSocket(); return false; } else { if (dwSend == 0) { #ifdef _ZZYDEBUG GC_TRACE("Error3"); #endif WSACloseEvent(over.hEvent); CloseSocket(); return false; } // 计算剩余发送字节数 wsabuf.len -= dwSend; dwTotalSend += dwSend; if(wsabuf.len <= 0) { break; } else { wsabuf.buf += dwSend; } } } }//while (1) 发送未结束 // 发送完成 if(over.hEvent) { WSACloseEvent(over.hEvent); } return true; }
unsigned int __stdcall CxServerSocketTCP::WorkerThread( LPVOID lpParam ) { char * pRecvBuffer = NULL; ServerThreadContext* pContext = (ServerThreadContext*) lpParam; CxServerSocketTCP *pThis = (CxServerSocketTCP *)pContext->pThis; XTRACE( _T("Starting thread [%p]0x%x\r\n"), pContext, pContext->hThread ); if ( !pContext->bListen ) pThis->OnClientConnected( pContext, pContext->strClientIP, pContext->nClientPort ); const int nRecvBufferSize = pThis->m_nMaxRecvBufferSize; if ( !(pRecvBuffer = (char *)xmalloc(nRecvBufferSize)) ) return 0; int nEventIndex; WSANETWORKEVENTS hNetworkEvents; BOOL bWork = TRUE; while ( bWork ) { nEventIndex = WSAWaitForMultipleEvents( 2, pContext->hNetEvent, FALSE, 500, FALSE ); nEventIndex -= WSA_WAIT_EVENT_0; for ( int ix=nEventIndex ; ix<2 ; ix++ ) { nEventIndex = WSAWaitForMultipleEvents( 1, &pContext->hNetEvent[ix], TRUE, 0, FALSE ); if ( (nEventIndex == WSA_WAIT_FAILED ) ) continue; else if ( (nEventIndex==WSA_WAIT_TIMEOUT) ) { } else { if ( ix == 1 ) { WSAEnumNetworkEvents( pContext->hSocket, pContext->hNetEvent[1], &hNetworkEvents ); if ( hNetworkEvents.lNetworkEvents & FD_READ ) { if ( hNetworkEvents.iErrorCode[FD_READ_BIT] != 0 ) { XTRACE( _T("Socket Read Error![%p]\r\n"), pContext ); break; } int nRecvBytes = recv( pContext->hSocket, pRecvBuffer, nRecvBufferSize, 0 ); if ( nRecvBytes > 0 ) { //XTRACE( _T("%d bytes received!\r\n"), nRecvBytes ); pThis->ProcessBuffer( pContext, pRecvBuffer, nRecvBytes ); } else { char szBye[3] = { 0, }; send( pContext->hSocket, szBye, 3, 0 ); shutdown( pContext->hSocket, SD_BOTH ); closesocket( pContext->hSocket ); XTRACE( _T("Closed socket handle [%p]%x\r\n"), pContext, pContext->hSocket ); pContext->hSocket = INVALID_SOCKET; if ( pContext->bListen ) pThis->OnStopServer(); else { pThis->OnClientDisconnected( pContext->strClientIP, pContext->nClientPort ); bWork = FALSE; } } } if ( hNetworkEvents.lNetworkEvents & FD_ACCEPT ) { if ( hNetworkEvents.iErrorCode[FD_ACCEPT_BIT] != 0 ) { XTRACE( _T("[%p] Accept Error!\r\n"), pContext ); } SOCKADDR_IN addrinClient; int nAddrSize = sizeof(SOCKADDR_IN); SOCKET hClientSocket = ::accept( pContext->hSocket, reinterpret_cast<struct sockaddr *>(&addrinClient), &nAddrSize ); if ( hClientSocket == INVALID_SOCKET ) { XTRACE( _T("[%p] accept() failed: %d\r\n"), pContext, WSAGetLastError() ); bWork = FALSE; break; } int nRet; int nMaxSendBufferSize = MAX_SEND_BUF_SIZE; int nMaxRecvBufferSize = MAX_RECV_BUF_SIZE; nRet = ::setsockopt( hClientSocket, SOL_SOCKET, SO_SNDBUF, (const char*)&nMaxSendBufferSize, sizeof(int) ); nRet = ::setsockopt( hClientSocket, SOL_SOCKET, SO_RCVBUF, (const char*)&nMaxRecvBufferSize, sizeof(int) ); int nLen = sizeof(int); nRet = ::getsockopt( hClientSocket, SOL_SOCKET, SO_SNDBUF, (char*)&nMaxSendBufferSize, &nLen ); nLen = sizeof(int); nRet = ::getsockopt( hClientSocket, SOL_SOCKET, SO_RCVBUF, (char*)&nMaxRecvBufferSize, &nLen ); CxString strClientIP; int nPort; TCHAR szClientAddr[50]={0,}; DWORD dwSize = sizeof(szClientAddr); SOCKADDR* pClientSockAddr = (SOCKADDR*)&addrinClient; CxString strClientSockAddr; if ( WSAAddressToString( pClientSockAddr, sizeof(SOCKADDR), NULL, szClientAddr, &dwSize) != SOCKET_ERROR ) { strClientSockAddr = szClientAddr; } int nColonPos = strClientSockAddr.ReverseFind( _T(':') ); strClientIP = strClientSockAddr.Left( nColonPos ); strClientSockAddr.Delete( 0, nColonPos+1 ); nPort = _tcstol(strClientSockAddr, NULL, 10); ServerThreadContext* pThreadContext = new ServerThreadContext; pThreadContext->hSocket = hClientSocket; pThreadContext->hThread = NULL; pThreadContext->pThis = pThis; pThreadContext->hNetEvent[0] = pThis->m_hCleanupEvent; pThreadContext->hNetEvent[1] = WSA_INVALID_EVENT; pThreadContext->IoBuffer.Create( pThis->GetIOBufferSize() ); pThreadContext->IoBuffer.Clear(); pThreadContext->bListen = FALSE; pThreadContext->strClientIP = strClientIP; pThreadContext->nClientPort = nPort; pThreadContext->dwUserData = 0; pThreadContext->hNetEvent[1] = WSACreateEvent(); if ( WSAEventSelect( pThreadContext->hSocket, pThreadContext->hNetEvent[1], FD_READ|FD_CLOSE ) == SOCKET_ERROR ) { XTRACE( _T("WSAEventSelect() error\r\n") ); break; } unsigned int nThreadID = 0; pThreadContext->hThread = (HANDLE)::_beginthreadex( NULL, 0, WorkerThread, pThreadContext, 0, &nThreadID ); if ( pThreadContext->hThread == NULL ) { delete pThreadContext; break; } CloseHandle( pThreadContext->hThread ); } if ( hNetworkEvents.lNetworkEvents & FD_CLOSE ) // ¿¬°á Á¾·á { if ( hNetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0 ) { XTRACE( _T("Abnormal closed...!!!\r\n") ); } else { WSACloseEvent( pContext->hNetEvent[1] ); pContext->hNetEvent[1] = WSA_INVALID_EVENT; } char szBye[3] = { 0, }; send( pContext->hSocket, szBye, 3, 0 ); shutdown( pContext->hSocket, SD_BOTH ); closesocket( pContext->hSocket ); XTRACE( _T("Closed socket handle [%p]%x\r\n"), pContext, pContext->hSocket ); pContext->hSocket = INVALID_SOCKET; if ( pContext->bListen ) pThis->OnStopServer(); else { pThis->OnClientDisconnected( pContext->strClientIP, pContext->nClientPort ); bWork = FALSE; } break; } } else { bWork = FALSE; break; } } } } if ( pRecvBuffer ) xfree(pRecvBuffer); XTRACE( _T("Exit thread [%p]0x%x\r\n"), pContext, pContext->hThread ); if ( !pContext->bListen ) { delete pContext; } _endthreadex(0); return 0; }
// 비동기 입출력 처리 함수 DWORD WINAPI WorkerThread(LPVOID arg) { int retval; while(1){ // 이벤트 객체 관찰 DWORD index = WSAWaitForMultipleEvents(nTotalSockets, EventArray, FALSE, WSA_INFINITE, FALSE); if(index == WSA_WAIT_FAILED) continue; index -= WSA_WAIT_EVENT_0; WSAResetEvent(EventArray[index]); if(index == 0) continue; // 클라이언트 정보 얻기 SOCKETINFO *ptr = SocketInfoArray[index]; SOCKADDR_IN clientaddr; int addrlen = sizeof(clientaddr); getpeername(ptr->sock, (SOCKADDR *)&clientaddr, &addrlen); // 비동기 입출력 결과 확인 DWORD cbTransferred, flags; retval = WSAGetOverlappedResult(ptr->sock, &ptr->overlapped, &cbTransferred, FALSE, &flags); if(retval == FALSE || cbTransferred == 0){ RemoveSocketInfo(index); printf("[TCP 서버] 클라이언트 종료: IP 주소=%s, 포트 번호=%d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port)); continue; } // 데이터 전송량 갱신 if(ptr->recvbytes == 0){ ptr->recvbytes = cbTransferred; ptr->sendbytes = 0; // 받은 데이터 출력 ptr->buf[ptr->recvbytes] = '\0'; printf("[TCP/%s:%d] %s\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), ptr->buf); } else{ ptr->sendbytes += cbTransferred; } if(ptr->recvbytes > ptr->sendbytes){ // 데이터 보내기 ZeroMemory(&ptr->overlapped, sizeof(ptr->overlapped)); ptr->overlapped.hEvent = EventArray[index]; ptr->wsabuf.buf = ptr->buf + ptr->sendbytes; ptr->wsabuf.len = ptr->recvbytes - ptr->sendbytes; DWORD sendbytes; retval = WSASend(ptr->sock, &ptr->wsabuf, 1, &sendbytes, 0, &ptr->overlapped, NULL); if(retval == SOCKET_ERROR){ if(WSAGetLastError() != WSA_IO_PENDING){ err_display("WSASend()"); } continue; } } else{ ptr->recvbytes = 0; // 데이터 받기 ZeroMemory(&ptr->overlapped, sizeof(ptr->overlapped)); ptr->overlapped.hEvent = EventArray[index]; ptr->wsabuf.buf = ptr->buf; ptr->wsabuf.len = BUFSIZE; DWORD recvbytes; flags = 0; retval = WSARecv(ptr->sock, &ptr->wsabuf, 1, &recvbytes, &flags, &ptr->overlapped, NULL); if(retval == SOCKET_ERROR){ if(WSAGetLastError() != WSA_IO_PENDING){ err_display("WSARecv()"); } continue; } } } }
LWS_EXTERN int _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) { struct lws_context_per_thread *pt; WSANETWORKEVENTS networkevents; struct lws_pollfd *pfd; struct lws *wsi; unsigned int i; DWORD ev; int n; /* stay dead once we are dead */ if (context == NULL || !context->vhost_list) return 1; pt = &context->pt[tsi]; if (!pt->service_tid_detected) { struct lws _lws; memset(&_lws, 0, sizeof(_lws)); _lws.context = context; pt->service_tid = context->vhost_list-> protocols[0].callback(&_lws, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); pt->service_tid_detected = 1; } if (timeout_ms < 0) { if (lws_service_flag_pending(context, tsi)) { /* any socket with events to service? */ for (n = 0; n < (int)pt->fds_count; n++) { int m; if (!pt->fds[n].revents) continue; m = lws_service_fd_tsi(context, &pt->fds[n], tsi); if (m < 0) return -1; /* if something closed, retry this slot */ if (m) n--; } } return 0; } if (context->event_loop_ops->run_pt) context->event_loop_ops->run_pt(context, tsi); for (i = 0; i < pt->fds_count; ++i) { pfd = &pt->fds[i]; if (!(pfd->events & LWS_POLLOUT)) continue; wsi = wsi_from_fd(context, pfd->fd); if (!wsi || wsi->listener) continue; if (wsi->sock_send_blocking) continue; pfd->revents = LWS_POLLOUT; n = lws_service_fd(context, pfd); if (n < 0) return -1; /* * Force WSAWaitForMultipleEvents() to check events * and then return immediately. */ timeout_ms = 0; /* if something closed, retry this slot */ if (n) i--; } /* * is there anybody with pending stuff that needs service forcing? */ if (!lws_service_adjust_timeout(context, 1, tsi)) { /* -1 timeout means just do forced service */ _lws_plat_service_tsi(context, -1, pt->tid); /* still somebody left who wants forced service? */ if (!lws_service_adjust_timeout(context, 1, pt->tid)) /* yes... come back again quickly */ timeout_ms = 0; } if (timeout_ms) { lws_usec_t t; lws_pt_lock(pt, __func__); /* don't stay in poll wait longer than next hr timeout */ t = __lws_hrtimer_service(pt); if ((lws_usec_t)timeout_ms * 1000 > t) timeout_ms = (int)(t / 1000); lws_pt_unlock(pt); } for (n = 0; n < (int)pt->fds_count; n++) WSAEventSelect(pt->fds[n].fd, pt->events, FD_READ | (!!(pt->fds[n].events & LWS_POLLOUT) * FD_WRITE) | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE | FD_QOS | FD_ROUTING_INTERFACE_CHANGE | FD_ADDRESS_LIST_CHANGE); ev = WSAWaitForMultipleEvents(1, &pt->events, FALSE, timeout_ms, FALSE); if (ev == WSA_WAIT_EVENT_0) { unsigned int eIdx; #if defined(LWS_WITH_TLS) if (pt->context->tls_ops && pt->context->tls_ops->fake_POLLIN_for_buffered) pt->context->tls_ops->fake_POLLIN_for_buffered(pt); #endif for (eIdx = 0; eIdx < pt->fds_count; ++eIdx) { unsigned int err; if (WSAEnumNetworkEvents(pt->fds[eIdx].fd, pt->events, &networkevents) == SOCKET_ERROR) { lwsl_err("WSAEnumNetworkEvents() failed " "with error %d\n", LWS_ERRNO); return -1; } if (!networkevents.lNetworkEvents) networkevents.lNetworkEvents = LWS_POLLOUT; pfd = &pt->fds[eIdx]; pfd->revents = (short)networkevents.lNetworkEvents; err = networkevents.iErrorCode[FD_CONNECT_BIT]; if ((networkevents.lNetworkEvents & FD_CONNECT) && err && err != LWS_EALREADY && err != LWS_EINPROGRESS && err != LWS_EWOULDBLOCK && err != WSAEINVAL) { lwsl_debug("Unable to connect errno=%d\n", err); pfd->revents |= LWS_POLLHUP; } if (pfd->revents & LWS_POLLOUT) { wsi = wsi_from_fd(context, pfd->fd); if (wsi) wsi->sock_send_blocking = 0; } /* if something closed, retry this slot */ if (pfd->revents & LWS_POLLHUP) --eIdx; if (pfd->revents) { recv(pfd->fd, NULL, 0, 0); lws_service_fd_tsi(context, pfd, tsi); } } } else if (ev == WSA_WAIT_TIMEOUT) { lws_service_fd(context, NULL); } else if (ev == WSA_WAIT_FAILED) return 0; return 0; }
static gpointer receiver_thread ( gpointer data ) { pgm_sock_t* rx_sock = (pgm_sock_t*)data; const long iov_len = 20; const long ev_len = 1; struct pgm_msgv_t msgv[iov_len]; #ifdef CONFIG_HAVE_EPOLL struct epoll_event events[ev_len]; /* wait for maximum 1 event */ const int efd = epoll_create (IP_MAX_MEMBERSHIPS); if (efd < 0) { g_error ("epoll_create failed errno %i: \"%s\"", errno, strerror(errno)); g_main_loop_quit (g_loop); return NULL; } if (pgm_epoll_ctl (rx_sock, efd, EPOLL_CTL_ADD, EPOLLIN) < 0) { g_error ("pgm_epoll_ctl failed errno %i: \"%s\"", errno, strerror(errno)); g_main_loop_quit (g_loop); return NULL; } struct epoll_event event; event.events = EPOLLIN; event.data.fd = g_quit_pipe[0]; if (epoll_ctl (efd, EPOLL_CTL_ADD, g_quit_pipe[0], &event) < 0) { g_error ("epoll_ctl failed errno %i: \"%s\"", errno, strerror(errno)); g_main_loop_quit (g_loop); return NULL; } #elif defined(CONFIG_HAVE_POLL) int n_fds = 2; struct pollfd fds[ 1 + n_fds ]; #elif defined(G_OS_UNIX) /* HAVE_SELECT */ int n_fds; fd_set readfds; #else /* G_OS_WIN32 */ SOCKET recv_sock, pending_sock; DWORD cEvents = PGM_RECV_SOCKET_READ_COUNT + 1; WSAEVENT waitEvents[ PGM_RECV_SOCKET_READ_COUNT + 1 ]; socklen_t socklen = sizeof (SOCKET); waitEvents[0] = g_quit_event; waitEvents[1] = WSACreateEvent (); pgm_getsockopt (rx_sock, IPPROTO_PGM, PGM_RECV_SOCK, &recv_sock, &socklen); WSAEventSelect (recv_sock, waitEvents[1], FD_READ); waitEvents[2] = WSACreateEvent (); pgm_getsockopt (rx_sock, IPPROTO_PGM, PGM_PENDING_SOCK, &pending_sock, &socklen); WSAEventSelect (pending_sock, waitEvents[2], FD_READ); #endif /* !CONFIG_HAVE_EPOLL */ do { struct timeval tv; #ifndef _WIN32 int timeout; #else DWORD dwTimeout, dwEvents; #endif size_t len; pgm_error_t* pgm_err = NULL; const int status = pgm_recvmsgv (rx_sock, msgv, G_N_ELEMENTS(msgv), 0, &len, &pgm_err); switch (status) { case PGM_IO_STATUS_NORMAL: on_msgv (msgv, len); break; case PGM_IO_STATUS_TIMER_PENDING: { socklen_t optlen = sizeof (tv); pgm_getsockopt (rx_sock, IPPROTO_PGM, PGM_TIME_REMAIN, &tv, &optlen); } goto block; case PGM_IO_STATUS_RATE_LIMITED: { socklen_t optlen = sizeof (tv); pgm_getsockopt (rx_sock, IPPROTO_PGM, PGM_RATE_REMAIN, &tv, &optlen); } /* fall through */ case PGM_IO_STATUS_WOULD_BLOCK: block: #ifdef CONFIG_HAVE_EPOLL timeout = PGM_IO_STATUS_WOULD_BLOCK == status ? -1 : ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); epoll_wait (efd, events, G_N_ELEMENTS(events), timeout /* ms */); #elif defined(CONFIG_HAVE_POLL) timeout = PGM_IO_STATUS_WOULD_BLOCK == status ? -1 : ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); memset (fds, 0, sizeof(fds)); fds[0].fd = g_quit_pipe[0]; fds[0].events = POLLIN; pgm_poll_info (rx_sock, &fds[1], &n_fds, POLLIN); poll (fds, 1 + n_fds, timeout /* ms */); #elif defined(G_OS_UNIX) /* HAVE_SELECT */ FD_ZERO(&readfds); FD_SET(g_quit_pipe[0], &readfds); n_fds = g_quit_pipe[0] + 1; pgm_select_info (rx_sock, &readfds, NULL, &n_fds); select (n_fds, &readfds, NULL, NULL, PGM_IO_STATUS_RATE_LIMITED == status ? &tv : NULL); #else /* G_OS_WIN32 */ dwTimeout = PGM_IO_STATUS_WOULD_BLOCK == status ? WSA_INFINITE : ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); dwEvents = WSAWaitForMultipleEvents (cEvents, waitEvents, FALSE, dwTimeout, FALSE); switch (dwEvents) { case WSA_WAIT_EVENT_0+1: WSAResetEvent (waitEvents[1]); break; case WSA_WAIT_EVENT_0+2: WSAResetEvent (waitEvents[2]); break; default: break; } #endif /* !CONFIG_HAVE_EPOLL */ break; default: if (pgm_err) { g_warning ("%s", pgm_err->message); pgm_error_free (pgm_err); pgm_err = NULL; } if (PGM_IO_STATUS_ERROR == status) break; } } while (!g_quit); #ifdef CONFIG_HAVE_EPOLL close (efd); #elif defined(G_OS_WIN32) WSACloseEvent (waitEvents[1]); WSACloseEvent (waitEvents[2]); # if (__STDC_VERSION__ < 199901L) g_free (waitHandles); # endif #endif return NULL; }
DWORD WINAPI WorkerThreadCallback(LPVOID lpParameter) { DWORD Flags; LPSOCKET_INFORMATION_CALLBACK SocketInfo; WSAEVENT EventArray[1]; DWORD Index; DWORD RecvBytes; // Save the accept event in the event array EventArray[0] = (WSAEVENT) lpParameter; while(TRUE) { // Wait for accept() to signal an event and also process WorkerRoutine() returns while(TRUE) { Index = WSAWaitForMultipleEvents(1, EventArray, FALSE, WSA_INFINITE, TRUE); if (Index == WSA_WAIT_FAILED) { printf("WSAWaitForMultipleEvents() failed with error %d\n", WSAGetLastError()); return FALSE; } else printf("WSAWaitForMultipleEvents() should be OK!\n"); if (Index != WAIT_IO_COMPLETION) { // An accept() call event is ready - break the wait loop break; } } /* The WSAResetEvent function resets the state * of the specified event object to nonsignaled. */ WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]); // Create a socket information structure to associate with the accepted socket if ((SocketInfo = (LPSOCKET_INFORMATION_CALLBACK) GlobalAlloc(GPTR, sizeof(SOCKET_INFORMATION_CALLBACK))) == NULL) { printf("GlobalAlloc() failed with error %d\n", GetLastError()); return FALSE; } else printf("GlobalAlloc() for SOCKET_INFORMATION is OK!\n"); // Fill in the details of our accepted socket SocketInfo->Socket = AcceptSocketCallback; ZeroMemory(&(SocketInfo->Overlapped), sizeof(WSAOVERLAPPED)); SocketInfo->BytesSEND = 0; SocketInfo->BytesRECV = 0; SocketInfo->DataBuf.len = DEFAULT_BUFLEN; SocketInfo->DataBuf.buf = SocketInfo->Buffer; Flags = 0; if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes, &Flags, &(SocketInfo->Overlapped), WorkerRoutineCallback) == SOCKET_ERROR) { if (WSAGetLastError() != WSA_IO_PENDING) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); return FALSE; } } else printf("WSARecv() is OK!\n"); printf("Socket %d got connected...\n", AcceptSocketCallback); } return TRUE; }
//////////////////////////////////////////////////////////////////////////////// // 函数名:INT SendData( // SOCKET hSocket, // LPCSTR pszBuffer, // INT nBufferSize, // DWORD dwTimeout ) // 用 途:发送数据 // 对全局变量的影响:无 // 参 数: // hSocket : 待发送的套接字 // pszBuffer : 发送数据缓冲区 // nBufferSize : 缓冲区大小 // dwTimeout : 发送超时 // 返回值:INT // >=0 : 成功,已成功发送的字节数 // <0 : 失败(SOCKET_FAIL:-1) //////////////////////////////////////////////////////////////////////////////// INT CBufSocket::SendData(SOCKET hSocket, LPCSTR pszBuffer, INT nBufferSize, DWORD dwTimeout) { HANDLE hWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hWriteEvent == NULL) { SetLastError( (INT)GetLastError() ); return (SOCKET_FAIL); } INT nSendBytes = 0; for (;;) { //////////////////////////////////////////////////////////////// // 发送数据成功 if ((nSendBytes = SendOnce(hSocket, pszBuffer, nBufferSize)) >= 0) break; INT nErrorCode = -nSendBytes; if (nErrorCode != WSAEWOULDBLOCK) { CloseHandle(hWriteEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } /////////////////////////////////////////////////////////////////////////////// // 睡眠一段时间 /////////////////////////////////////////////////////////////////////////////// Sleep(DEFAULT_BLOCKED_SNDRCV_SLEEP); // 注册FD_WRITE | FD_CLOSE 事件 if( WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, FD_WRITE|FD_CLOSE) == SOCKET_ERROR) { CloseHandle(hWriteEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } // 等待事件发生 DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hWriteEvent, TRUE,dwTimeout, TRUE); if (dwWaitResult != WSA_WAIT_EVENT_0) { // 清除网络事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hWriteEvent,&NetEvent) == SOCKET_ERROR) { // 清除网络事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } if( ( NetEvent.lNetworkEvents == FD_CLOSE ) || ( NetEvent.lNetworkEvents == FD_WRITE && NetEvent.iErrorCode[FD_WRITE_BIT] !=0 ) ) // 发生错误 { // 清除网络事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } // 清除网络事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); } CloseHandle(hWriteEvent); return (nSendBytes); }
//////////////////////////////////////////////////////////////////////////////// // 函数名:INT SendTo( // SOCKET hSocket, // CONST struct sockaddr * pTo, // INT nToLen, // LPCSTR pszBuffer, // INT nBufferSize, // DWORD dwTimeout ) // 用 途:发送数据报 // 对全局变量的影响:无 // 参 数: // hSocket : 套接字 // pTo : 数据报的目的地址 // nToLen : 地址长度 // pszBuffer : 缓冲区 // nBufferSize : 缓冲区大小 // dwTimeout : 超时 // 返回值:INT //////////////////////////////////////////////////////////////////////////////// INT CBufSocket::SendTo(SOCKET hSocket, CONST struct sockaddr * pTo,INT nToLen,LPCSTR pszBuffer, INT nBufferSize, DWORD dwTimeout) { HANDLE hWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hWriteEvent == NULL) { SetLastError( (INT)GetLastError() ); return (SOCKET_FAIL); } DWORD dwSendBytes = 0, dwFlags = 0; WSABUF WSABuff; ZeroMemory(&WSABuff,sizeof(WSABUF)); WSABuff.len = nBufferSize; WSABuff.buf = (CHAR *) pszBuffer; for (;;) { if (WSASendTo( hSocket, &WSABuff, 1, &dwSendBytes, dwFlags,pTo, nToLen, NULL, NULL) == SOCKET_SUCCESS) break; if (WSAGetLastError() != WSAEWOULDBLOCK) { CloseHandle(hWriteEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } ////////////////////////////////////////////////////////////////////////// // 睡眠一段时间 ///////////////////////////////////////////////////////////////////////// Sleep(DEFAULT_BLOCKED_SNDRCV_SLEEP); // 注册FD_WRITE事件 if( WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, FD_WRITE) == SOCKET_ERROR) { CloseHandle(hWriteEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hWriteEvent, TRUE,dwTimeout, TRUE); if( dwWaitResult != WSA_WAIT_EVENT_0 ) { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hWriteEvent,&NetEvent) == SOCKET_ERROR) { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } if(NetEvent.iErrorCode[FD_WRITE_BIT] !=0 ) // 发生错误 { // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); CloseHandle(hWriteEvent); SetLastError(NetEvent.iErrorCode[FD_WRITE_BIT]); return (SOCKET_FAIL); } //////////////////////////////////////////////////////////////// // 注销事件 WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0); } CloseHandle(hWriteEvent); return ((INT) dwSendBytes); }
//////////////////////////////////////////////////////////////////////////////// // 函数名:INT RecvData( // SOCKET hSocket, // OUT CHAR *pszBuffer, // INT nBufferSize, // DWORD dwTimeout ) // 用 途:接收数据(阻塞直至收到数据为止) // 对全局变量的影响:无 // 参 数: // hSocket : 待接收数据的套接字 // pszBuffer : 缓冲区 // nBufferSize : 缓冲区大小 // dwTimeout : 接收超时 // 返回值:INT // >=0 : 接收到的字节数 // <0 : 失败(SOCKET_FAIL: -1) //////////////////////////////////////////////////////////////////////////////// INT CBufSocket::RecvData(SOCKET hSocket, OUT CHAR *pszBuffer, INT nBufferSize, DWORD dwTimeout) { HANDLE hReadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hReadEvent == NULL) { SetLastError( (INT)GetLastError() ); return ( SOCKET_FAIL ); } INT nRecvBytes = 0; DWORD dwWaitResult; for (;;) { // 注册FD_READ | FD_CLOSE 事件 // (因为可能在等待FD_READ事件中,对方关闭套接字,所以要关注FD_CLOSE) if( WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, FD_READ | FD_CLOSE) == SOCKET_ERROR) { CloseHandle(hReadEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } // 等等FD_READ | FD_CLOSE事件的发生 //dwWaitResult = WSAWaitForMultipleEvents(1, &hReadEvent, TRUE,dwTimeout, TRUE); //seawind DWORD dwBeginTime = GetTickCount(); BOOL bDataCome = FALSE; while(GetTickCount() - dwBeginTime < dwTimeout) { //和HttpDownload,FtpDownload类共享一个Event Handle if (m_hStopEvent != NULL && (WaitForSingleObject(m_hStopEvent, 0) == WAIT_OBJECT_0)) { //要赶快跳走,用户点了Stop CloseHandle(hReadEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); //break; } dwWaitResult = WSAWaitForMultipleEvents(1, &hReadEvent, TRUE, 0, TRUE); if (dwWaitResult == WSA_WAIT_EVENT_0) { //数据来啦 bDataCome = TRUE; break; } //空出CPU时间 Sleep(DEFAULT_BLOCKED_SNDRCV_SLEEP); } //if (dwWaitResult != WSA_WAIT_EVENT_0) if (!bDataCome) { // 清除事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } ////////////////////////////////////////////////////////////// /// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该 /// 进一步检查网络是否发生错误 /////////////////////////////////////////////////////////////// WSANETWORKEVENTS NetEvent; if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hReadEvent,&NetEvent) == SOCKET_ERROR) { // 清除事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); SetLastError( WSAGetLastError() ); return (SOCKET_FAIL); } //判断发生了什么事件 FD_READ 或 FD_CLOSE if( ( NetEvent.lNetworkEvents == FD_CLOSE ) || ( NetEvent.lNetworkEvents == FD_READ && NetEvent.iErrorCode[FD_READ_BIT] !=0 ) ) // 发生错误 { // 清除事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); CloseHandle(hReadEvent); SetLastError(WSAGetLastError() ); return (SOCKET_FAIL); } //////////////////////////////////////////////////////////////// // 清除事件 WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0); // 接收数据 if ((nRecvBytes = RecvOnce(hSocket, pszBuffer, nBufferSize)) >= 0) break; // 跳出循环 INT nErrorCode = -nRecvBytes; if ( nErrorCode != WSAEWOULDBLOCK ) //太多的未完成重叠操作 { CloseHandle(hReadEvent); SetLastError( nErrorCode ); return (SOCKET_FAIL); } //阻塞住了 //////////////////////////////////////////////////////////////////////// // 如果发生阻塞,就等待一定时间后重试,以免CPU轮询浪费时间 //////////////////////////////////////////////////////////////////////// Sleep(DEFAULT_BLOCKED_SNDRCV_SLEEP); } CloseHandle(hReadEvent); return (nRecvBytes); }
DWORD WINAPI CNetworkMgr::AcceptThread( void *pParam ) { CNetworkMgr *pNetworkSrv = (CNetworkMgr *)pParam; HANDLE hComPort = pNetworkSrv->m_hCompPort; //完成端口 SOCKET sListen = pNetworkSrv->m_socket; //监听套接字 SOCKET sAccept = INVALID_SOCKET; //接受客户端连接的套接字 //sockaddr_in addrClient; //客户端SOCKET地址 while ( pNetworkSrv->m_bRunning ) { DWORD dwRet; dwRet = WSAWaitForMultipleEvents( 1, &pNetworkSrv->m_hEvent, FALSE, 100, FALSE ); //等待网络事件 if ( !pNetworkSrv->m_bRunning ) //服务器停止服务 { break; } if ( dwRet == WSA_WAIT_TIMEOUT ) //函数调用超时 { continue; } WSANETWORKEVENTS events; int nRet = WSAEnumNetworkEvents( pNetworkSrv->m_socket, pNetworkSrv->m_hEvent, &events ); if ( SOCKET_ERROR == nRet ) { pNetworkSrv->ShowErrorMsg( "WSAEnumNetworkEvents() failed!\n" ); break; } if ( events.lNetworkEvents & FD_ACCEPT ) { if ( events.iErrorCode[FD_ACCEPT_BIT] == 0 && pNetworkSrv->m_bRunning) { sockaddr_in addrClient; int addrClientLen = sizeof( addrClient ); sAccept = WSAAccept( sListen, (LPSOCKADDR)&addrClient, &addrClientLen, NULL, 0 ); if ( INVALID_SOCKET == sAccept ) { pNetworkSrv->ShowErrorMsg( "WSAAccept() failed!\n" ); break; } CConnect *pConnect = new CConnect( sAccept, addrClient ); if ( CreateIoCompletionPort( (HANDLE)sAccept, hComPort, (DWORD)pConnect, 0 ) == NULL ) { return -1; } //加入管理客户端链表 CConnectMgr *pConnectMgr = CConnectMgr::GetInstance(); pConnectMgr->AddConnect( pConnect ); if ( !pConnect->AsyncRecvHead() ) { pConnectMgr->DeleteConnect( pConnect ); } } } } //释放资源 CConnectMgr *pConnectMgr = CConnectMgr::GetInstance(); pConnectMgr->DeleteAllConnect(); pConnectMgr->Release(); //Sleep( 10000 ); printf( "AcceptThread return\n" ); return 0; }
unsigned __stdcall #endif nak_routine ( void* arg ) { /* dispatch loop */ pgm_sock_t* nak_sock = (pgm_sock_t*)arg; #ifndef _WIN32 int fds; fd_set readfds; #else SOCKET recv_sock, repair_sock, pending_sock; DWORD cEvents = PGM_SEND_SOCKET_READ_COUNT + 1; WSAEVENT waitEvents[ PGM_SEND_SOCKET_READ_COUNT + 1 ]; DWORD dwTimeout, dwEvents; socklen_t socklen = sizeof (SOCKET); waitEvents[0] = terminateEvent; waitEvents[1] = WSACreateEvent(); waitEvents[2] = WSACreateEvent(); waitEvents[3] = WSACreateEvent(); assert (3 == PGM_SEND_SOCKET_READ_COUNT); pgm_getsockopt (nak_sock, IPPROTO_PGM, PGM_RECV_SOCK, &recv_sock, &socklen); WSAEventSelect (recv_sock, waitEvents[1], FD_READ); pgm_getsockopt (nak_sock, IPPROTO_PGM, PGM_REPAIR_SOCK, &repair_sock, &socklen); WSAEventSelect (repair_sock, waitEvents[2], FD_READ); pgm_getsockopt (nak_sock, IPPROTO_PGM, PGM_PENDING_SOCK, &pending_sock, &socklen); WSAEventSelect (pending_sock, waitEvents[3], FD_READ); #endif /* !_WIN32 */ do { struct timeval tv; char buf[4064]; pgm_error_t* pgm_err = NULL; const int status = pgm_recv (nak_sock, buf, sizeof(buf), 0, NULL, &pgm_err); switch (status) { case PGM_IO_STATUS_TIMER_PENDING: { socklen_t optlen = sizeof (tv); pgm_getsockopt (sock, IPPROTO_PGM, PGM_TIME_REMAIN, &tv, &optlen); } goto block; case PGM_IO_STATUS_RATE_LIMITED: { socklen_t optlen = sizeof (tv); pgm_getsockopt (sock, IPPROTO_PGM, PGM_RATE_REMAIN, &tv, &optlen); } case PGM_IO_STATUS_WOULD_BLOCK: block: #ifndef _WIN32 fds = terminate_pipe[0] + 1; FD_ZERO(&readfds); FD_SET(terminate_pipe[0], &readfds); pgm_select_info (nak_sock, &readfds, NULL, &fds); fds = select (fds, &readfds, NULL, NULL, PGM_IO_STATUS_WOULD_BLOCK == status ? NULL : &tv); #else dwTimeout = PGM_IO_STATUS_WOULD_BLOCK == status ? WSA_INFINITE : (DWORD)((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); dwEvents = WSAWaitForMultipleEvents (cEvents, waitEvents, FALSE, dwTimeout, FALSE); switch (dwEvents) { case WSA_WAIT_EVENT_0+1: WSAResetEvent (waitEvents[1]); break; case WSA_WAIT_EVENT_0+2: WSAResetEvent (waitEvents[2]); break; case WSA_WAIT_EVENT_0+3: WSAResetEvent (waitEvents[3]); break; default: break; } #endif /* !_WIN32 */ break; default: if (pgm_err) { fprintf (stderr, "%s\n", pgm_err->message ? pgm_err->message : "(null)"); pgm_error_free (pgm_err); pgm_err = NULL; } if (PGM_IO_STATUS_ERROR == status) break; } } while (!is_terminated); #ifndef _WIN32 return NULL; #else WSACloseEvent (waitEvents[1]); WSACloseEvent (waitEvents[2]); WSACloseEvent (waitEvents[3]); _endthread(); return 0; #endif }
void main(void) { DWORD EventTotal = 0; WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS]; LPSOCKET_INFORMATION SocketArray[WSA_MAXIMUM_WAIT_EVENTS]; CHAR AcceptBuffer[2 * (sizeof(SOCKADDR_IN) + 16)]; WSAOVERLAPPED ListenOverlapped; DWORD Bytes; DWORD Index; DWORD Flags; DWORD BytesTransferred; LPSOCKET_INFORMATION SI; WSADATA wsaData; SOCKET ListenSocket, AcceptSocket; SOCKADDR_IN InternetAddr; DWORD RecvBytes, SendBytes; DWORD i; INT Ret; if ((Ret = WSAStartup(0x0202,&wsaData)) != 0) { printf("WSAStartup failed with error %d\n", Ret); WSACleanup(); return; } if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("Failed to get a socket %d\n", WSAGetLastError()); return; } InternetAddr.sin_family = AF_INET; InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY); InternetAddr.sin_port = htons(PORT); if (bind(ListenSocket, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR) { printf("bind() failed with error %d\n", WSAGetLastError()); return; } if (listen(ListenSocket, 5)) { printf("listen() failed with error %d\n", WSAGetLastError()); return; } // Setup the listening socket for connections. if ((AcceptSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("Failed to get a socket %d\n", WSAGetLastError()); return; } ZeroMemory(&ListenOverlapped, sizeof(OVERLAPPED)); if ((EventArray[0] = ListenOverlapped.hEvent = WSACreateEvent()) == WSA_INVALID_EVENT) { printf("WSACreateEvent failed with error %d\n", WSAGetLastError()); return; } EventTotal = 1; if (AcceptEx(ListenSocket, AcceptSocket, (PVOID) AcceptBuffer, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, &Bytes, &ListenOverlapped) == FALSE) if (WSAGetLastError() != ERROR_IO_PENDING) { printf("AcceptEx failed with error %d\n", WSAGetLastError()); return; } // Process asynchronous AcceptEx, WSASend, WSARecv requests. while(TRUE) { if ((Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED) { printf("WSAWaitForMultipleEvents failed %d\n", WSAGetLastError()); return; } // If the event triggered was zero then a connection attempt was made // on our listening socket. if ((Index - WSA_WAIT_EVENT_0) == 0) { // Check the returns from the overlapped I/O operation on the listening // socket. if (WSAGetOverlappedResult(ListenSocket, &(ListenOverlapped), &BytesTransferred, FALSE, &Flags) == FALSE) { printf("WSAGetOverlappedResult failed with error %d\n", WSAGetLastError()); return; } printf("Socket %d connected\n", AcceptSocket); if (EventTotal > WSA_MAXIMUM_WAIT_EVENTS) { printf("Too many connections - closing socket.\n"); closesocket(AcceptSocket); continue; } else { // Create a socket information structure to associate with the accepted socket. if ((SocketArray[EventTotal] = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR, sizeof(SOCKET_INFORMATION))) == NULL) { printf("GlobalAlloc() failed with error %d\n", GetLastError()); return; } // Fill in the details of our accepted socket. SocketArray[EventTotal]->Socket = AcceptSocket; ZeroMemory(&(SocketArray[EventTotal]->Overlapped), sizeof(OVERLAPPED)); SocketArray[EventTotal]->BytesSEND = 0; SocketArray[EventTotal]->BytesRECV = 0; SocketArray[EventTotal]->DataBuf.len = DATA_BUFSIZE; SocketArray[EventTotal]->DataBuf.buf = SocketArray[EventTotal]->Buffer; if ((SocketArray[EventTotal]->Overlapped.hEvent = EventArray[EventTotal] = WSACreateEvent()) == WSA_INVALID_EVENT) { printf("WSACreateEvent() failed with error %d\n", WSAGetLastError()); return; } // Post a WSARecv request to to begin receiving data on the socket if (WSARecv(SocketArray[EventTotal]->Socket, &(SocketArray[EventTotal]->DataBuf), 1, &RecvBytes, &Flags, &(SocketArray[EventTotal]->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); return; } } EventTotal++; } // Make a new socket for accepting future connections and post another // AcceptEx call. if ((AcceptSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("Failed to get a socket %d\n", WSAGetLastError()); return; } WSAResetEvent(EventArray[0]); ZeroMemory(&ListenOverlapped, sizeof(OVERLAPPED)); ListenOverlapped.hEvent = EventArray[0]; if (AcceptEx(ListenSocket, AcceptSocket, (PVOID) AcceptBuffer, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, &Bytes, &ListenOverlapped) == FALSE) if (WSAGetLastError() != ERROR_IO_PENDING) { printf("AcceptEx failed with error %d\n", WSAGetLastError()); return; } continue; } SI = SocketArray[Index - WSA_WAIT_EVENT_0]; WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]); if (WSAGetOverlappedResult(SI->Socket, &(SI->Overlapped), &BytesTransferred, FALSE, &Flags) == FALSE) { printf("WSAGetOverlappedResult failed with error %d\n", WSAGetLastError()); return; } // First check to see if the peer has closed the connection and if so // then close the socket and cleanup the SOCKET_INFORMATION structure // associated with the socket. if (BytesTransferred == 0) { printf("Closing socket %d\n", SI->Socket); if (closesocket(SI->Socket) == SOCKET_ERROR) { printf("closesocket() failed with error %d\n", WSAGetLastError()); } GlobalFree(SI); WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]); // Cleanup SocketArray and EventArray by removing the socket event handle // and socket information structure if they are not at the end of the // arrays. if ((Index - WSA_WAIT_EVENT_0) + 1 != EventTotal) for (i = Index - WSA_WAIT_EVENT_0; i < EventTotal; i++) { EventArray[i] = EventArray[i + 1]; SocketArray[i] = SocketArray[i + 1]; } EventTotal--; continue; } // Check to see if the BytesRECV field equals zero. If this is so, then // this means a WSARecv call just completed so update the BytesRECV field // with the BytesTransferred value from the completed WSARecv() call. if (SI->BytesRECV == 0) { SI->BytesRECV = BytesTransferred; SI->BytesSEND = 0; } else { SI->BytesSEND += BytesTransferred; } if (SI->BytesRECV > SI->BytesSEND) { // Post another WSASend() request. // Since WSASend() is not gauranteed to send all of the bytes requested, // continue posting WSASend() calls until all received bytes are sent. ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED)); SI->Overlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0]; SI->DataBuf.buf = SI->Buffer + SI->BytesSEND; SI->DataBuf.len = SI->BytesRECV - SI->BytesSEND; if (WSASend(SI->Socket, &(SI->DataBuf), 1, &SendBytes, 0, &(SI->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSASend() failed with error %d\n", WSAGetLastError()); return; } } } else { SI->BytesRECV = 0; // Now that there are no more bytes to send post another WSARecv() request. Flags = 0; ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED)); SI->Overlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0]; SI->DataBuf.len = DATA_BUFSIZE; SI->DataBuf.buf = SI->Buffer; if (WSARecv(SI->Socket, &(SI->DataBuf), 1, &RecvBytes, &Flags, &(SI->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); return; } } } } }