// // Function: RemoveSocketObjByHandle // // Description: // Remove the socket object structure from the list of objects that // matches the socket handle. // void RemoveSocketObjByHandle(SOCKET s) { SOCKET_OBJ *obj; obj = FindSocketObj(s); if (obj) { RemoveSocketObj(obj); } return; }
bool MightyTCPCompletionPortServer::CloseLink(const string & strLinkNo) { PCompletionPortIOObject controlHandle=NULL; controlHandle=SearchSocketObj(strLinkNo); if (controlHandle!=NULL) { RemoveSocketObj(controlHandle); return true; } return false; }
BOOL HandleIOProcessTCPServer::HandleIO(PSOCKET_OBJ pSocket) { // 获取具体发生的网络事件 WSANETWORKEVENTS event; ::WSAEnumNetworkEvents(pSocket->s, pSocket->event, &event); do { if(event.lNetworkEvents & FD_READ) // 套节字可读 { if(event.iErrorCode[FD_READ_BIT] == 0) { char tcpPackage[4096]={0}; int nRecv = ::recv(pSocket->s,tcpPackage,4096,0); /*if(nRecv > 0) { szText[nRecv] = '\0'; printf("接收到数据:%s \n", szText); }*/ ((MightyTCPEventSelectServer *)(m_userInstance.InstanceUserData_))->m_pNotifyCallBack->OnRecvData(tcpPackage,nRecv,pSocket->identityIDKey); } else break; } else if(event.lNetworkEvents & FD_CLOSE) // 套节字关闭 { break; } else if(event.lNetworkEvents & FD_WRITE) // 套节字可写 { if(event.iErrorCode[FD_WRITE_BIT] == 0) { } else break; } return TRUE; } while(FALSE); // 套节字关闭,或者有错误发生,程序都会转到这里来执行 RemoveSocketObj(pSocket); return FALSE; }
void MightyTCPCompletionPortServer::HandleIO(DWORD dwKey, PCompletionPort_BufObj pBuffer, DWORD dwTrans, int nError) { PCompletionPortIOObject pContext = (PCompletionPortIOObject)dwKey; //首先减少套节字上的未决I/O计数 if(pContext != NULL) { if(pBuffer->nOperation == OP_READ) pContext->nOutstandingRecv --; else if(pBuffer->nOperation == OP_WRITE) pContext->nOutstandingSend --; // 检查套节字是否已经被我们关闭 if(pContext->nCondition) { if(pContext->nOutstandingRecv == 0 && pContext->nOutstandingSend == 0) { RemoveSocketObj(pContext); } // 释放已关闭套节字的未决I/O ReleaseBuffer(pBuffer); return; } } else { RemovePendingAccept(pBuffer); } //检查套节字上发生的错误,如果有的话,通知用户,然后关闭套节字 if(nError != NO_ERROR) { if(pBuffer->nOperation != OP_ACCEPT) { //if(nError==ERROR_NETNAME_DELETED) RemoveSocketObj(pContext); if(pContext->nOutstandingRecv == 0 && pContext->nOutstandingSend == 0) { //ReleaseContext(pContext); } } else // 在监听套节字上发生错误,也就是监听套节字处理的客户出错了 { // 客户端出错,释放I/O缓冲区 if(pBuffer->sAccept!= INVALID_SOCKET) { ::closesocket(pBuffer->sAccept); pBuffer->sAccept= INVALID_SOCKET; } } ReleaseBuffer(pBuffer); return; } // 开始处理 if(pBuffer->nOperation == OP_ACCEPT) { if(dwTrans == 0) { if(pBuffer->sAccept!= INVALID_SOCKET) { ::closesocket(pBuffer->sAccept); pBuffer->sAccept= INVALID_SOCKET; } } else { // 为新接受的连接申请客户上下文对象 PCompletionPortIOObject pClient =GetSocketObj(pBuffer->sAccept); if(pClient != NULL) { if(InsertSocketObj(pClient)==0) { // 取得客户地址 int nLocalLen, nRmoteLen; LPSOCKADDR pLocalAddr, pRemoteAddr; m_lpfnGetAcceptExSockaddrs( pBuffer->buff, pBuffer->nLen - ((sizeof(sockaddr_in) + 16) * 2), sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, (SOCKADDR **)&pLocalAddr, &nLocalLen, (SOCKADDR **)&pRemoteAddr, &nRmoteLen); memcpy(&pClient->addrLocal, pLocalAddr, nLocalLen); memcpy(&pClient->addrRemote, pRemoteAddr, nRmoteLen); // 关联新连接到完成端口对象 ::CreateIoCompletionPort((HANDLE)pClient->s, m_hCompletionPort, (DWORD)pClient, 0); // 通知用户 pBuffer->nLen = dwTrans; m_pNotifyCallBack->OnRecvData(pBuffer->buff,dwTrans,pClient->identityIDKey); // 向新连接投递几个Read请求,这些空间在套节字关闭或出错时释放 for(int i=0; i<5; i++) { PCompletionPort_BufObj p = AllocateBuffer(pClient,2048); if(p != NULL) { if(!PostRecv(p)) { RemoveSocketObj(pClient); break; } } } } else // 连接数量已满,关闭连接 { RemoveSocketObj(pClient); } } else { // 资源不足,关闭与客户的连接即可 ::closesocket(pBuffer->sAccept); pBuffer->sAccept= INVALID_SOCKET; } } // Accept请求完成,释放I/O缓冲区 ReleaseBuffer(pBuffer); // 通知监听线程继续再投递一个Accept请求 ::InterlockedIncrement(&m_nRepostCount); ::SetEvent(m_hRepostEvent); } else if(pBuffer->nOperation == OP_READ) { if(dwTrans == 0) // 对方关闭套节字 { // 先通知用户 pBuffer->nLen = 0; RemoveSocketObj(pContext); // 释放客户上下文和缓冲区对象 if(pContext->nOutstandingRecv == 0 && pContext->nOutstandingSend == 0) { //ReleaseContext(pContext); } //ReleaseBuffer(pBuffer); } else { pBuffer->nLen = dwTrans; // 按照I/O投递的顺序读取接收到的数据 PCompletionPort_BufObj pNextIO = GetNextReadBuffer(pContext, pBuffer); while(pNextIO != NULL) { m_pNotifyCallBack->OnRecvData(pNextIO->buff,dwTrans,pContext->identityIDKey); // 增加要读的序列号的值 ::InterlockedIncrement((LONG*)&pContext->nCurrentReadSequence); // 释放这个已完成的I/O ReleaseBuffer(pNextIO); pNextIO= GetNextReadBuffer(pContext, NULL); } // 继续投递一个新的接收请求 pBuffer = AllocateBuffer(pContext,4096); if(pBuffer == NULL || !PostRecv(pBuffer)) { //closeAConnection(pContext); } } } else if(pBuffer->nOperation == OP_WRITE) { if(dwTrans == 0) // 对方关闭套节字 { // 先通知用户 pBuffer->nLen = 0; RemoveSocketObj(pContext); // 再关闭连接 //CloseAConnection(pContext); // 释放客户上下文和缓冲区对象 if(pContext->nOutstandingRecv == 0 && pContext->nOutstandingSend == 0) { //ReleaseContext(pContext); } //ReleaseBuffer(pBuffer); } else { // 写操作完成,通知用户 pBuffer->nLen = dwTrans; //OnWriteCompleted(pContext, pBuffer); // 释放SendText函数申请的缓冲区 ReleaseBuffer(pBuffer); } } }
// // Function: HandleIo // // Description: // This function handles the IO on a socket. First, the events signaled // on the socket are enuemrated, then the appropriate handler routine // for the event is called. // int HandleIo(THREAD_OBJ *thread, SOCKET_OBJ *sock) { WSANETWORKEVENTS nevents; int rc; // Enumerate the events rc = WSAEnumNetworkEvents( sock->s, sock->event, &nevents ); if (rc == SOCKET_ERROR) { fprintf(stderr, "HandleIo: WSAEnumNetworkEvents failed: %d\n", WSAGetLastError()); return SOCKET_ERROR; } if (nevents.lNetworkEvents & FD_READ) { // Check for read error if (nevents.iErrorCode[FD_READ_BIT] == 0) { rc = ReceivePendingData(sock); if (rc == -1) { RemoveSocketObj(thread, sock); FreeSocketObj(sock); return SOCKET_ERROR; } rc = SendPendingData(sock); if (rc == -1) { RemoveSocketObj(thread, sock); FreeSocketObj(sock); return SOCKET_ERROR; } } else { fprintf(stderr, "HandleIo: FD_READ error %d\n", nevents.iErrorCode[FD_READ_BIT]); RemoveSocketObj(thread, sock); FreeSocketObj(sock); return SOCKET_ERROR; } } if (nevents.lNetworkEvents & FD_WRITE) { // Check for write error if (nevents.iErrorCode[FD_WRITE_BIT] == 0) { rc = SendPendingData(sock); if (rc == -1) { RemoveSocketObj(thread, sock); FreeSocketObj(sock); return SOCKET_ERROR; } } else { fprintf(stderr, "HandleIo: FD_WRITE error %d\n", nevents.iErrorCode[FD_WRITE_BIT]); return SOCKET_ERROR; } } if (nevents.lNetworkEvents & FD_CLOSE) { // Check for close error if (nevents.iErrorCode[FD_CLOSE_BIT] == 0) { // Socket has been indicated as closing so make sure all the data // has been read while (1) { rc = ReceivePendingData(sock); if (rc == -1) { RemoveSocketObj(thread, sock); FreeSocketObj(sock); return SOCKET_ERROR; } else if (rc != 0) { continue; } else { break; } } // See if there is any data pending, if so try to send it rc = SendPendingData(sock); if (rc == -1) { RemoveSocketObj(thread, sock); FreeSocketObj(sock); return SOCKET_ERROR; } } else { fprintf(stderr, "HandleIo: FD_CLOSE error %d\n", nevents.iErrorCode[FD_CLOSE_BIT]); RemoveSocketObj(thread, sock); FreeSocketObj(sock); return SOCKET_ERROR; } } return NO_ERROR; }
// // Function: WindowProc // // Description: // This is the window procedure which handles the window messages for // our hidden window. It handles all the WM_SOCKET messages and performs // the correct actions for each message type (FD_READ, FD_WRITE, etc.). // LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { SOCKET_OBJ *sockobj=NULL, *newsock=NULL; int rc; if (uMsg == WM_SOCKET) { // Check for an error on the socket if (WSAGETSELECTERROR(lParam)) { // An error occured on the socket, close it down fprintf(stderr, "Socket failed with error %d\n", WSAGETSELECTERROR(lParam)); closesocket(wParam); RemoveSocketObjByHandle(wParam); } else { // Find the socket object for this event sockobj = FindSocketObj(wParam); if (sockobj == NULL) return 0; switch (WSAGETSELECTEVENT(lParam)) { case FD_ACCEPT: // Get a new object for the client socket newsock = GetSocketObj(INVALID_SOCKET); newsock->s = accept( wParam, (SOCKADDR *)&newsock->addr, &newsock->addrlen ); if (newsock->s == INVALID_SOCKET) { fprintf(stderr, "accept failed: %d\n", WSAGetLastError()); break; } InterlockedIncrement(&gCurrentConnections); // Create a socket information structure to associate with the // socket for processing I/O. InsertSocketObj(newsock); /* printf("Accepted connection from: "); PrintAddress((SOCKADDR *)&newsock->addr, newsock->addrlen); printf("\n"); */ rc = WSAAsyncSelect( newsock->s, hwnd, WM_SOCKET, FD_READ | FD_WRITE | FD_CLOSE ); if (rc == SOCKET_ERROR) { fprintf(stderr, "WSAAsyncSelect failed: %d\n", WSAGetLastError()); return -1; } break; case FD_READ: rc = ReceivePendingData(sockobj); if (rc == -1) { RemoveSocketObj(sockobj); break; } else if (rc != WSAEWOULDBLOCK) { PostMessage(hwnd, WM_SOCKET, wParam, FD_READ); } // // Don't break fall through and attempt to send data // case FD_WRITE: // // Send routine automatically tries to send all queued buffers. // rc = SendPendingData(sockobj); if (rc == -1) { RemoveSocketObj(sockobj); } break; case FD_CLOSE: sockobj->closing = TRUE; // // Post an FD_READ message to force another receive // This is to ensure we recv() until 0 is returned. // PostMessage(hwnd, WM_SOCKET, wParam, FD_READ); break; default: printf("Unknown message received: %d\n", WSAGETSELECTEVENT(lParam)); break; } } return 0; } return DefWindowProc(hwnd, uMsg, wParam, lParam); }