SOCKET WSocket::Accept() { return WSAAccept(m_hSocket,NULL,NULL,NULL,0); }
void main(void) { SOCKADDR_IN InternetAddr; SOCKET Listen; SOCKET Accept; HANDLE CompletionPort; SYSTEM_INFO SystemInfo; LPPER_HANDLE_DATA PerHandleData; LPPER_IO_OPERATION_DATA PerIoData; int i; DWORD RecvBytes; DWORD Flags; DWORD ThreadID; WSADATA wsaData; DWORD Ret; if ((Ret = WSAStartup(0x0202, &wsaData)) != 0) { printf("WSAStartup failed with error %d\n", Ret); return; } // Setup an I/O completion port. if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL) { printf( "CreateIoCompletionPort failed with error: %d\n", GetLastError()); return; } // Determine how many processors are on the system. GetSystemInfo(&SystemInfo); // Create worker threads based on the number of processors available on the // system. Create two worker threads for each processor. for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++) { HANDLE ThreadHandle; // Create a server worker thread and pass the completion port to the thread. if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort, 0, &ThreadID)) == NULL) { printf("CreateThread() failed with error %d\n", GetLastError()); return; } // Close the thread handle CloseHandle(ThreadHandle); } // Create a listening socket if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("WSASocket() failed with error %d\n", WSAGetLastError()); return; } InternetAddr.sin_family = AF_INET; InternetAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); InternetAddr.sin_port = htons(PORT); if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR) { printf("bind() failed with error %d\n", WSAGetLastError()); return; } // Prepare socket for listening if (listen(Listen, 5) == SOCKET_ERROR) { printf("listen() failed with error %d\n", WSAGetLastError()); return; } // Accept connections and assign to the completion port. sockaddr_in client; int len=sizeof(client); while(TRUE) { ZeroMemory(&client,sizeof(sockaddr_in)); if ((Accept = WSAAccept(Listen, PSOCKADDR(&client), &len, NULL, 0)) == SOCKET_ERROR) { printf("WSAAccept() failed with error %d\n", WSAGetLastError()); return; } // Create a socket information structure to associate with the socket if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL) { printf("GlobalAlloc() failed with error %d\n", GetLastError()); return; } // Associate the accepted socket with the original completion port. PerHandleData->Socket = Accept; if (CreateIoCompletionPort((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData, 0) == NULL) { printf("CreateIoCompletionPort failed with error %d\n", GetLastError()); return; } // Create per I/O socket information structure to associate with the // WSARecv call below. if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA))) == NULL) { printf("GlobalAlloc() failed with error %d\n", GetLastError()); return; } ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); strncpy(PerIoData->ip,inet_ntoa(client.sin_addr),20); PerIoData->port=ntohs(client.sin_port); PerIoData->BytesSEND = 0; PerIoData->BytesRECV = 0; PerIoData->DataBuf.len = DATA_BUFSIZE; PerIoData->DataBuf.buf = PerIoData->Buffer; printf("[%s:%u] has established!!\n",PerIoData->ip,PerIoData->port); Flags = 0; if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); return; } } } }
void AcceptThreadFunc(void) { int retval = 0; struct sockaddr_in listenAddr; int newID = -1; SOCKET acceptSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); if (INVALID_SOCKET == acceptSocket) { DisplayErrMsg("AcceptThread :: acceptSocket Fail !!", WSAGetLastError()); return; } // bind() : 소켓의 지역 IP주소와 지역 포트 번호를 결정, C++11의 bind라는 함수와 혼동 때문에::범위확인 연산자와 같이 사용. // msdn - The bind functio associates a local address with a socket // listenAddr : 소켓 주소 구조체를 지역 IP주소와 지역 포트 번호로 초기화하여 전달한다. // AF_INET : 인터넷 주초 체계(IPv4)를 사용한다는 의미 // INADDR_ANY : 서버의 지역 IP주소를 설정하는데 있어 다음과 같이 설정을 하면 서버가 IP주소를 2 개 이상 보유한 경우 // (multihomed host라고 부름), 클라이언트가 어느 IP 주소로 접속하든 받아들일 수 있음 // bind 함수의 2번째 인자는 항상 (SOCKADDR*)형으로 반환해야 함 ZeroMemory(&listenAddr, sizeof(listenAddr)); listenAddr.sin_family = AF_INET; listenAddr.sin_addr.s_addr = htonl(INADDR_ANY); listenAddr.sin_port = htons(MY_SERVER_PORT); ZeroMemory(&listenAddr.sin_zero, 8); retval = ::bind(acceptSocket, reinterpret_cast<sockaddr*>(&listenAddr), sizeof(listenAddr)); if (SOCKET_ERROR == retval) { DisplayErrMsg("AcceptThread :: bind Fail !!", WSAGetLastError()); exit(1); } // listen() : 소켓의 TCP 포트 상태를 LISTENING으로 바꾼다. 이는 클라이언트 접속을 받아들일 수 있는 상태가 됨을 의미 // msdn - The listen function places a socket in a state in which it is listening for an incomming connection. // SOMAXCONN : 클라이언트의 접속 정보는 연결 큐에 저장되는데, backlog는 이 연결 큐의 길이를 나타냄. // SOMAXCONN의 의미는 하부 프로토콜에서 지원 가능한 최댓값을 사용 listen(acceptSocket, SOMAXCONN); if (SOCKET_ERROR == retval) { DisplayErrMsg("AcceptThread :: listen Fail !!", WSAGetLastError()); exit(1); } while (true) { struct sockaddr_in clientAddr; int addrSize = sizeof(clientAddr); // 접속한 클라이언트의 새 ID // accept() : 접속한 클라이언트와 통신할 수 있도록 새로운 소켓을 생성해서 리턴 또한 접속한 클라이언트의 주소정보도 알려줌 // : 서버입장에서는 원격 IP주소와 원격 포트번호, 클라이언트 입장에서는 지역 IP 주소와 지역 포트 번호 // WSAAccept() : ? // msdn - The WSAAccept function conditionally accepts a connection based on the return value of a condition, // provides quality of service flow specifications, and allows the transfer of connection data. SOCKET newClientSocket = WSAAccept(acceptSocket, reinterpret_cast<sockaddr*>(&clientAddr), &addrSize, NULL, NULL); if (INVALID_SOCKET == newClientSocket) { DisplayErrMsg("AcceptThread :: WSAAccept Fail !!", WSAGetLastError()); break; } // 접속한 클라이언트의 새로운 ID 부여하는 구간 newID++; // Accept를 받은 이후에 등록을 해주어야 함 HANDLE result = CreateIoCompletionPort(reinterpret_cast<HANDLE>(newClientSocket), ghIOCP, newID, 0); if (NULL == result) { DisplayErrMsg("AcceptThread :: CreateIoCompletionPort Fail !!", WSAGetLastError()); closesocket(newClientSocket); continue; } gClientInfoMAP.Insert(newID); gClientInfoMAP.GetData(newID)->isConnect = true; gClientInfoMAP.GetData(newID)->socket = newClientSocket; memset(&gClientInfoMAP.GetData(newID)->recvOverlap.originalOverlap, 0, sizeof(WSAOVERLAPPED)); ZeroMemory(gClientInfoMAP.GetData(newID)->recvOverlap.buffer, MAX_BUFF_SIZE); gClientInfoMAP.GetData(newID)->recvOverlap.wsaBuf.buf = reinterpret_cast<CHAR*>(gClientInfoMAP.GetData(newID)->recvOverlap.buffer); gClientInfoMAP.GetData(newID)->recvOverlap.wsaBuf.len = MAX_BUFF_SIZE; gClientInfoMAP.GetData(newID)->recvOverlap.operation = OP_RECV; gClientInfoMAP.GetData(newID)->recvOverlap.packetSize = 0; ZeroMemory(gClientInfoMAP.GetData(newID)->packetBuf, MAX_BUFF_SIZE); gClientInfoMAP.GetData(newID)->previousDataSize = 0; gClientInfoMAP.GetData(newID)->player.roomNo = 0; gClientInfoMAP.GetData(newID)->player.pos.x = DEFAULT_POS_X; gClientInfoMAP.GetData(newID)->player.pos.y = DEFAULT_POS_Y; gClientInfoMAP.GetData(newID)->player.pos.z = DEFAULT_POS_Z; // 새로운 소켓 Recv 수행 DWORD flags = 0; // WSARecv() : 5번째, 6번째 두 인자를 NULL 값으로 사용하면 recv() 함수처럼 동기 함수로 동작 retval = WSARecv(newClientSocket, &gClientInfoMAP.GetData(newID)->recvOverlap.wsaBuf, 1, NULL, &flags, &gClientInfoMAP.GetData(newID)->recvOverlap.originalOverlap, NULL); if (0 != retval) { int errNo = WSAGetLastError(); if (WSA_IO_PENDING != errNo) { DisplayErrMsg("AcceptThread :: WSARecv", errNo); } } // 새로운 클라이언트 접속 알림 Packet::SetID clientSetIDPacket; clientSetIDPacket.size = sizeof(Packet::SetID); clientSetIDPacket.type = (BYTE)PacketType::SetID; clientSetIDPacket.id = newID; SendPacket(newID, reinterpret_cast<unsigned char*>(&clientSetIDPacket)); // Output std::string debugText = "AcceptThread :: ID " + std::to_string(newID) + " client Accept Success !!"; DisplayDebugText(debugText); } return; }
DWORD WINAPI IocpServerWorker(LPVOID p) { SYSTEM_INFO SystemInfo; DWORD ThreadID; SOCKET Accept; int nRet; int ClientIndex; SOCKADDR_IN cAddr; IN_ADDR cInAddr; int cAddrlen = sizeof( cAddr ); LPPER_SOCKET_CONTEXT lpPerSocketContext = NULL; DWORD RecvBytes; DWORD Flags=0; InitializeCriticalSection(&criti); GetSystemInfo(&SystemInfo); g_dwThreadCount = SystemInfo.dwNumberOfProcessors * 2; //MyFix 3 if ( g_dwThreadCount > 16 ) { g_dwThreadCount = 16; LogAdd(" **** Worker Thread Max Count Fix 16ea ****"); } //ms_exc.registration.TryLevel = 0; __try { g_CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if ( g_CompletionPort == NULL) { LogAdd("CreateIoCompletionPort failed with error: %d", GetLastError()); __leave; } for(DWORD dwCPU = 0; dwCPU < g_dwThreadCount; dwCPU++) { HANDLE ThreadHandle; // Create a server worker thread and pass the completion port to the thread. ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, g_CompletionPort, 0, &ThreadID); if ( ThreadHandle == NULL) { LogAdd("CreateThread() failed with error %d", GetLastError()); __leave; } g_ThreadHandles[dwCPU] = ThreadHandle; CloseHandle(ThreadHandle); } if (!CreateListenSocket() ) __leave; while(TRUE) { Accept = WSAAccept(g_Listen, (LPSOCKADDR)&cAddr, &cAddrlen, NULL, 0); if (Accept==SOCKET_ERROR) { EnterCriticalSection(&criti); LogAdd("WSAAccept() failed with error %d", WSAGetLastError()); LeaveCriticalSection(&criti); continue; } EnterCriticalSection(&criti); memcpy( &cInAddr, &cAddr.sin_addr.s_addr, 4 ); ClientIndex = gObjAddSearch(Accept, inet_ntoa(cInAddr) ); if ( ClientIndex == -1 ) { LogAddL("error-L2 : ClientIndex = -1"); closesocket(Accept); LeaveCriticalSection(&criti); continue; } if (UpdateCompletionPort(Accept, ClientIndex, 1) == 0 ) { LogAddL("error-L1 : %d %d CreateIoCompletionPort failed with error %d", Accept, ClientIndex, GetLastError() ); closesocket(Accept); LeaveCriticalSection(&criti); continue; } if (gObjAdd(Accept, inet_ntoa(cInAddr), ClientIndex) == -1 ) { LogAddL("error-L1 : %d %d gObjAdd() failed with error %d", Accept, ClientIndex, GetLastError() ); LeaveCriticalSection(&criti); closesocket(Accept); continue; } bool bCryptoOpenCS = g_CryptoSessionCS.Open(ClientIndex); bool bCryptoOpenSC = g_CryptoSessionSC.Open(ClientIndex); if ( !bCryptoOpenCS || !bCryptoOpenSC ) { g_CryptoSessionCS.Close(ClientIndex); g_CryptoSessionSC.Close(ClientIndex); LogAddL("error-L1 : %d %d Open Set Crypto Open failed with error", Accept, ClientIndex); LeaveCriticalSection(&criti); closesocket(Accept); continue; } memset(&gObj[ClientIndex].PerSocketContext->IOContext[0].Overlapped, 0, sizeof(OVERLAPPED)); memset(&gObj[ClientIndex].PerSocketContext->IOContext[1].Overlapped, 0, sizeof(OVERLAPPED)); gObj[ClientIndex].PerSocketContext->IOContext[0].wsabuf.buf = gObj[ClientIndex].PerSocketContext->IOContext[0].Buffer; gObj[ClientIndex].PerSocketContext->IOContext[0].wsabuf.len = MAX_IO_BUFFER_SIZE; gObj[ClientIndex].PerSocketContext->IOContext[0].nTotalBytes = 0; gObj[ClientIndex].PerSocketContext->IOContext[0].nSentBytes = 0; gObj[ClientIndex].PerSocketContext->IOContext[0].nWaitIO = 0; gObj[ClientIndex].PerSocketContext->IOContext[0].nSecondOfs = 0; gObj[ClientIndex].PerSocketContext->IOContext[0].IOOperation = RECV_IO; gObj[ClientIndex].PerSocketContext->IOContext[1].wsabuf.buf = gObj[ClientIndex].PerSocketContext->IOContext[0].Buffer; gObj[ClientIndex].PerSocketContext->IOContext[1].wsabuf.len = MAX_IO_BUFFER_SIZE; gObj[ClientIndex].PerSocketContext->IOContext[1].nTotalBytes= 0; gObj[ClientIndex].PerSocketContext->IOContext[1].nSentBytes = 0; gObj[ClientIndex].PerSocketContext->IOContext[1].nWaitIO = 0; gObj[ClientIndex].PerSocketContext->IOContext[1].nSecondOfs = 0; gObj[ClientIndex].PerSocketContext->IOContext[1].IOOperation = SEND_IO; gObj[ClientIndex].PerSocketContext->m_socket = Accept; gObj[ClientIndex].PerSocketContext->nIndex = ClientIndex; nRet = WSARecv(Accept, &(gObj[ClientIndex].PerSocketContext->IOContext[0].wsabuf), 1, &RecvBytes, &Flags, &(gObj[ClientIndex].PerSocketContext->IOContext[0].Overlapped), NULL); if( nRet == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING ) { LogAdd("error-L1 : WSARecv() failed with error %d", WSAGetLastError()); gObj[ClientIndex].PerSocketContext->IOContext[0].nWaitIO = 4; CloseClient(gObj[ClientIndex].PerSocketContext, FALSE); LeaveCriticalSection(&criti); continue; } gObj[ClientIndex].PerSocketContext->IOContext[0].nWaitIO = 1; gObj[ClientIndex].PerSocketContext->dwIOCount++; LeaveCriticalSection(&criti); SCPJoinResultSend(ClientIndex, 1); } } __finally { if( g_CompletionPort ) { for (DWORD i = 0; i < g_dwThreadCount; i++) PostQueuedCompletionStatus(g_CompletionPort, 0, 0, NULL); } if( g_CompletionPort ) { CloseHandle(g_CompletionPort); g_CompletionPort = NULL; } if (g_Listen != INVALID_SOCKET) { closesocket(g_Listen); g_Listen = INVALID_SOCKET; } } return TRUE; }
// Function: main() // Description: // This function parses arguments and starts either the client or server // depending on the arguments. The server will enumerate local ATM // interfaces if necessary and bind to a local address and wait for // client connections. The server handles the client connection in the // same thread as the listening socket. The client only handles one // connection and then exits. If running the client, create a socket // and connect to the server. Once connected, send a message and read it back int main_atm(int argc, char **argv) { WSADATA wsd; SOCKET s; DWORD dwAddrLen = sizeof(SOCKADDR_ATM); SOCKADDR_ATM atm_addr; int ret, i; char szAddress[41]; // Initialize Winsock and parse command line arguments if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) { printf("WSAStartup() failed with error code %d\n", WSAGetLastError()); return -1; } else printf("WSAStartup() is OK!\n"); // Find the protocol entry supporting ATM and create a socket lpSocketProtocol = FindProtocol_atm(); if (lpSocketProtocol == NULL) { printf("FindProtocol() returned NULL!\n"); return -1; } else printf("FindProtocol() is OK!\n"); s = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, lpSocketProtocol, 0, WSA_FLAG_OVERLAPPED); if (s == INVALID_SOCKET) { printf("WSASocket() failed with error code %d\n", WSAGetLastError()); return -1; } else printf("WSASocket() is OK!\n"); ValidateArgs_atm(argc, argv); ZeroMemory((PVOID)&atm_addr, sizeof(atm_addr)); atm_addr.satm_family = AF_ATM; atm_addr.satm_number.AddressType = ATM_NSAP; atm_addr.satm_number.NumofDigits = 20; atm_addr.satm_blli.Layer2Protocol = SAP_FIELD_ABSENT; atm_addr.satm_blli.Layer3Protocol = SAP_FIELD_ABSENT; atm_addr.satm_bhli.HighLayerInfoType = SAP_FIELD_ABSENT; // If an interface number was not supplied (i.e. a 38 character NSAP ATM address was supplied) if ((!bServer) || (dwInterface == -1)) { strncpy_s(&szAddress[0], sizeof(szAddress[0]),szServerAddr, 38); strncpy_s(&szAddress[38], sizeof(szAddress[38]),szPort, 2); szAddress[40] = 0; AtoH_atm((char *) &atm_addr.satm_number.Addr[0], szAddress, 20); } else { // An index was supplied, look it up and get its address if (GetATMAddress_atm(s, dwInterface, &atm_addr.satm_number) == FALSE) { printf("Unable to get ATM interface!\n"); } AtoH_atm((char *) &atm_addr.satm_number.Addr[19], szPort, 1); } if (bServer) { SOCKET sclient; SOCKADDR_ATM atm_client; int atmaddrsz = sizeof(SOCKADDR_ATM); DWORD dwClientAddrLen=MAX_ATM_ADDR_LEN; struct fd_set fdaccept; char recvbuf[MAX_BUFFER], szClientAddr[MAX_ATM_ADDR_LEN], szAddr[MAX_BUFFER]; dwAddrLen = MAX_BUFFER; // Print out the address we're binding to if (WSAAddressToString((LPSOCKADDR)&atm_addr, sizeof(atm_addr), lpSocketProtocol, (LPWSTR)szAddr, &dwAddrLen)) { printf("WSAAddressToString() failed with error code %d\n", WSAGetLastError()); } else printf("WSAAddressToString() is OK!\n"); printf("Binding to: <%s>\n", szAddr); if (bind(s, (SOCKADDR *)&atm_addr, sizeof(atm_addr)) == SOCKET_ERROR) { printf("bind() failed with error code %d\n", WSAGetLastError()); return -1; } else printf("bind() should be fine!\n"); if(listen(s, 7) == SOCKET_ERROR) printf("listen() failed with error code %d\n", WSAGetLastError()); else printf("listen() is OK! I am listening...\n"); FD_ZERO(&fdaccept); FD_SET(s, &fdaccept); if (select(0, &fdaccept, NULL, NULL, NULL) == SOCKET_ERROR) printf("Something wrong with select() with error code %d\n", WSAGetLastError()); else if (select(0, &fdaccept, NULL, NULL, NULL) == 0) printf("select() - the time limit expired!\n"); else printf("select() should be OK!\n"); sclient = WSAAccept(s, (SOCKADDR *)&atm_client, &atmaddrsz, NULL, 0); if (sclient == INVALID_SOCKET) { printf("WSAAccept() failed with error code %d\n", WSAGetLastError()); return -1; } else printf("WSAAccept() should be OK!\n"); ZeroMemory((PVOID)szClientAddr, MAX_ATM_ADDR_LEN); if (WSAAddressToString((LPSOCKADDR)&atm_client, sizeof(atm_client), lpSocketProtocol, (LPWSTR)szClientAddr, &dwClientAddrLen)) { printf("WSAAddressToString() failed with herror code %d\n", WSAGetLastError()); } else printf("WSAAddressToString() is OK!\n"); printf("Client's ATM ADDRESS: <%s>\n", szClientAddr); // Handle the client connection until it closes while (1) { ret = recv(sclient, recvbuf, MAX_BUFFER, 0); if (ret == SOCKET_ERROR) { if(WSAEDISCON == WSAGetLastError()) printf("recv() - a connection closed by peer...\n"); else printf("recv() failed with error code %d\n", WSAGetLastError()); return -1; } else if (ret == 0) { printf("recv() - a graceful close!\n"); break; } else printf("recv() is OK!\n"); recvbuf[ret] = '\0'; printf("Read: '%s'\n", recvbuf); ret = send(sclient, recvbuf, ret, 0); if (ret == SOCKET_ERROR) { if(WSAEDISCON == WSAGetLastError()) printf("send() - a connection closed by peer!\n"); else printf("send() failed with error code %d\n", WSAGetLastError()); return -1; } else printf("send() should be OK!\n"); printf("wrote %d bytes...\n", ret); } closesocket(sclient); } else { char sendbuf[MAX_BUFFER], szAddr[MAX_BUFFER]; dwAddrLen = MAX_BUFFER; // Connect and then send and recv data if (WSAAddressToString((LPSOCKADDR)&atm_addr, sizeof(atm_addr), lpSocketProtocol, (LPWSTR)szAddr, &dwAddrLen)) { printf("WSAAddressToString() failed with error code %d\n", WSAGetLastError()); } else printf("WSAAddressToString() is OK\n"); printf("Connect to: <%s>\n", szAddr); if (connect(s, (SOCKADDR *)&atm_addr, sizeof(atm_addr)) == SOCKET_ERROR) { printf("connect() failed with error code %d\n", WSAGetLastError()); return -1; } else printf("connect() is OK!\n"); memset(sendbuf, '$', 512); for(i=0; i < 10 ;i++) { ret = send(s, sendbuf, 64, 0); if (ret == SOCKET_ERROR) { if(WSAEDISCON == WSAGetLastError()) printf("send() - connection closed by peer!\n"); else printf("send() failed with error code %d\n", WSAGetLastError()); return -1; } else printf("send() should be OK!\n"); printf("Sent %d bytes\n", ret); ret = recv(s, sendbuf, ret, 0); if (ret == SOCKET_ERROR) { if(WSAEDISCON == WSAGetLastError()) printf("recv() - connection closed by peer!\n"); else printf("recv() failed with error code %d\n", WSAGetLastError()); return -1; } else if (ret == 0) { printf("recv() - a graceful close\n"); break; } else printf("recv() is OK!\n"); sendbuf[ret] = '\0'; printf("Read: '%s'\n", sendbuf); } } closesocket(s); WSACleanup(); return 0; }
static int acceptSocket(const char *webServerAddrs) { SOCKET hSock; int ipcFd = -1; for (;;) { struct sockaddr sockaddr; int sockaddrLen = sizeof(sockaddr); for (;;) { const struct timeval timeout = {1, 0}; fd_set readfds; FD_ZERO(&readfds); #pragma warning( disable : 4127 ) FD_SET((unsigned int) hListen, &readfds); #pragma warning( default : 4127 ) if (select(0, &readfds, NULL, NULL, &timeout) == 0) { if (shutdownPending) { OS_LibShutdown(); return -1; } } else { break; } } #if NO_WSAACEPT hSock = accept((SOCKET) hListen, &sockaddr, &sockaddrLen); if (hSock == INVALID_SOCKET) { break; } if (isAddrOK((struct sockaddr_in *) &sockaddr, webServerAddrs)) { break; } closesocket(hSock); #else hSock = WSAAccept((unsigned int) hListen, &sockaddr, &sockaddrLen, isAddrOKCallback, (DWORD) webServerAddrs); if (hSock != INVALID_SOCKET) { break; } if (WSAGetLastError() != WSAECONNREFUSED) { break; } #endif } if (hSock == INVALID_SOCKET) { /* Use FormatMessage() */ fprintf(stderr, "accept()/WSAAccept() failed: %d", WSAGetLastError()); return -1; } ipcFd = Win32NewDescriptor(FD_SOCKET_SYNC, hSock, -1); if (ipcFd == -1) { closesocket(hSock); } return ipcFd; }
void GTcpSvrServiceThread(PGTHREAD pThread) { DWORD dwResult; PGHND_DATA pClient; INT nResult; INT nLong; INT nLongBytes = sizeof(INT); DWORD dwTickCount; GLog_Write("GTcpSvrServiceThread:伺服线程开始"); for(;;) { #if(_RUN_INFO) pThread->dwState = GTHREAD_STATE_SLEEP; #endif if(!dwGTcpSvrListenerCount) { Sleep(1000); dwResult = WSA_WAIT_TIMEOUT; }else dwResult = WSAWaitForMultipleEvents(dwGTcpSvrListenerCount, hGTcpSvrListenerEvents, FALSE, 1000, FALSE); if(pThread->bIsShutdown) break; #if(_RUN_INFO) pThread->dwState = GTHREAD_STATE_WORKING1; pThread->dwRunCount++; #endif if(WSA_WAIT_TIMEOUT != dwResult) { dwResult -= WSA_WAIT_EVENT_0; WSAResetEvent(hGTcpSvrListenerEvents[dwResult]); if((dwGTcpSvrClientCount + dwGTcpSvrPendingAcceptCount >= dwGSockMaxNumberConnection) || (!GTcpSvr_PostAccept(pGTcpSvrListeners[dwResult], dwGSockNumberPostAccept))) { SOCKADDR_IN Addr; int nLen; nLen = sizeof(SOCKADDR_IN); closesocket(WSAAccept(pGTcpSvrListeners[dwResult]->Socket, (SOCKADDR*)&Addr, &nLen, NULL, 0)); if(dwGTcpSvrClientCount >= dwGSockMaxNumberConnection) GLog_Write("GTcpSvrServiceThread:超出连接限制"); else GLog_Write("GTcpSvrServiceThread:投递接受“GTcpSvr_PostAccept”失败"); #if(_OUTIODATA_INFO) std::stringstream ss; ss << "[GTcpSvrServiceThread]" << "[SvrClientCount:"<<dwGTcpSvrClientCount <<"|SvrPendingAcceptCount:" <<dwGTcpSvrPendingAcceptCount<< "]"; GLog_Write(const_cast<char*>(ss.str().c_str())); #endif } continue; } if(dwGSockAcceptBytes) { #if(_USE_INTERLOCKED_IN_LIST) GTcpSvr_LockPendingAcceptList(); #else EnterCriticalSection(>cpSvrPendingAcceptCS); #endif #if(_RUN_INFO) pThread->dwState = GTHREAD_STATE_WORKING2; #endif pClient = pGTcpSvrPendingAcceptHead; pGTcpSvrOvertimeCount = 0; while(pClient) { nResult = getsockopt(pClient->Socket, SOL_SOCKET, SO_CONNECT_TIME, (char *)&nLong, (PINT)&nLongBytes); if((SOCKET_ERROR != nResult) && (0xFFFFFFFF != nLong) && (dwGSockTimeAcceptOvertime < (DWORD)nLong)) { pGTcpSvrOvertimeClient[pGTcpSvrOvertimeCount] = pClient; pGTcpSvrOvertimeCount++; } pClient = pClient->pNext; } #if(_USE_INTERLOCKED_IN_LIST) GTcpSvr_UnlockPendingAcceptList(); #else LeaveCriticalSection(>cpSvrPendingAcceptCS); #endif #if(_RUN_INFO) pThread->dwState = GTHREAD_STATE_WORKING3; #endif while(pGTcpSvrOvertimeCount) //overtime send GIO_CLOSE { pGTcpSvrOvertimeCount--; pGTcpSvrOvertimeClient[pGTcpSvrOvertimeCount]->dwTickCountAcitve = dwTickCount; GTcpSvr_DoCloseClient(PGHND_DATA(pGTcpSvrOvertimeClient[pGTcpSvrOvertimeCount]->pOwner), pGTcpSvrOvertimeClient[pGTcpSvrOvertimeCount], GIO_CLOSE); } }//if(dwGSockAcceptBytes) if(dwGSockTimeIdleOvertime) { #if(_USE_INTERLOCKED_IN_LIST) GTcpSvr_LockClientList(); #else EnterCriticalSection(>cpSvrClientCS); #endif #if(_RUN_INFO) pThread->dwState = GTHREAD_STATE_WORKING4; #endif pClient = pGTcpSvrClientHead; pGTcpSvrOvertimeCount = 0; dwTickCount = GetTickCount(); while(pClient) {//QueryPerformanceCounter if(dwTickCount >= pClient->dwTickCountAcitve) nLong = dwTickCount - pClient->dwTickCountAcitve; else nLong = 0xFFFFFFFF - pClient->dwTickCountAcitve + dwTickCount; if((DWORD)nLong > dwGSockTimeIdleOvertime) { pGTcpSvrOvertimeClient[pGTcpSvrOvertimeCount] = pClient; pGTcpSvrOvertimeCount++; } pClient = pClient->pNext; } #if(_USE_INTERLOCKED_IN_LIST) GTcpSvr_UnlockClientList(); #else LeaveCriticalSection(>cpSvrClientCS); #endif #if(_RUN_INFO) pThread->dwState = GTHREAD_STATE_WORKING5; #endif while(pGTcpSvrOvertimeCount) { pGTcpSvrOvertimeCount--; pGTcpSvrOvertimeClient[pGTcpSvrOvertimeCount]->dwTickCountAcitve = dwTickCount; GTcpSvr_DoCloseClient(pGTcpSvrOvertimeClient[pGTcpSvrOvertimeCount], pGTcpSvrOvertimeClient[pGTcpSvrOvertimeCount], GIO_IDLE_OVERTIME); } }//if(dwGSockTimeIdleOvertime) }//for(;;) }
T_SOCKET _accept(T_SOCKET s, struct sockaddr *sock) { int len = sizeof(struct sockaddr); return (WSAAccept(s, sock, &len, NULL, NULL)); }
/*=== Main thread */ void* TSK_STDCALL tnet_transport_mainthread(void *param) { tnet_transport_t *transport = (tnet_transport_t*)param; transport_context_t *context = (transport_context_t*)transport->context; DWORD evt; WSANETWORKEVENTS networkEvents; DWORD flags = 0; int ret; struct sockaddr_storage remote_addr = { 0 }; WSAEVENT active_event; transport_socket_xt* active_socket; int index; TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type); while (TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started) { /* Wait for multiple events */ if ((evt = WSAWaitForMultipleEvents((DWORD)context->count, context->events, FALSE, WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED) { TNET_PRINT_LAST_ERROR("WSAWaitForMultipleEvents have failed."); goto bail; } if (!TSK_RUNNABLE(transport)->running && !TSK_RUNNABLE(transport)->started) { goto bail; } /* lock context */ tsk_safeobj_lock(context); /* Get active event and socket */ index = (evt - WSA_WAIT_EVENT_0); active_event = context->events[index]; if (!(active_socket = context->sockets[index])) { goto done; } /* Get the network events flags */ if (WSAEnumNetworkEvents(active_socket->fd, active_event, &networkEvents) == SOCKET_ERROR) { TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); TNET_PRINT_LAST_ERROR("WSAEnumNetworkEvents have failed."); tsk_safeobj_unlock(context); goto bail; } /*================== FD_ACCEPT ==================*/ if (networkEvents.lNetworkEvents & FD_ACCEPT) { tnet_fd_t fd; TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_ACCEPT", transport->description); if (networkEvents.iErrorCode[FD_ACCEPT_BIT]) { TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); TNET_PRINT_LAST_ERROR("ACCEPT FAILED."); goto done; } /* Accept the connection */ if ((fd = (tnet_fd_t)WSAAccept(active_socket->fd, NULL, NULL, AcceptCondFunc, (DWORD_PTR)context)) != INVALID_SOCKET) { /* Add the new fd to the server context */ addSocket(fd, transport->master->type, transport, tsk_true, tsk_false, tsk_null); if (active_socket->tlshandle) { transport_socket_xt* tls_socket; if ((tls_socket = getSocket(context, fd))) { if (tnet_tls_socket_accept(tls_socket->tlshandle)) { tnet_transport_remove_socket(transport, &fd); TNET_PRINT_LAST_ERROR("SSL_accept() failed"); goto done; } } } if (WSAEventSelect(fd, context->events[context->count - 1], FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR) { tnet_transport_remove_socket(transport, &fd); TNET_PRINT_LAST_ERROR("WSAEventSelect() have failed."); goto done; } TSK_RUNNABLE_ENQUEUE(transport, event_accepted, transport->callback_data, fd); } else { TNET_PRINT_LAST_ERROR("ACCEPT FAILED."); goto done; } } /*================== FD_CONNECT ==================*/ if (networkEvents.lNetworkEvents & FD_CONNECT) { TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_CONNECT", transport->description); if (networkEvents.iErrorCode[FD_CONNECT_BIT]) { tnet_fd_t fd = active_socket->fd; TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd); tnet_transport_remove_socket(transport, &fd); TNET_PRINT_LAST_ERROR("CONNECT FAILED."); goto done; } else { TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, active_socket->fd); active_socket->connected = 1; } } /*================== FD_READ ==================*/ if (networkEvents.lNetworkEvents & FD_READ) { DWORD readCount = 0; WSABUF wsaBuffer; /* TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_READ", transport->description); */ /* check whether the socket is paused or not */ if (active_socket->paused){ TSK_DEBUG_INFO("Socket is paused"); goto FD_READ_DONE; } if (networkEvents.iErrorCode[FD_READ_BIT]) { TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); TNET_PRINT_LAST_ERROR("READ FAILED."); goto done; } /* Retrieve the amount of pending data */ if (tnet_ioctlt(active_socket->fd, FIONREAD, &(wsaBuffer.len)) < 0) { TNET_PRINT_LAST_ERROR("IOCTLT FAILED."); goto done; } if (!wsaBuffer.len) { goto done; } /* Alloc data */ if (!(wsaBuffer.buf = tsk_calloc(wsaBuffer.len, sizeof(uint8_t)))) { goto done; } /* Retrieve the remote address */ if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { ret = tnet_getpeername(active_socket->fd, &remote_addr); } /* Receive the waiting data. */ if (active_socket->tlshandle) { int isEncrypted; tsk_size_t len = wsaBuffer.len; if (!(ret = tnet_tls_socket_recv(active_socket->tlshandle, &wsaBuffer.buf, &len, &isEncrypted))) { if (isEncrypted) { TSK_FREE(wsaBuffer.buf); goto done; } wsaBuffer.len = (ULONG)len; } } else { if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { ret = WSARecv(active_socket->fd, &wsaBuffer, 1, &readCount, &flags, 0, 0); } else { int len = sizeof(remote_addr); ret = WSARecvFrom(active_socket->fd, &wsaBuffer, 1, &readCount, &flags, (struct sockaddr*)&remote_addr, &len, 0, 0); } if (readCount < wsaBuffer.len) { wsaBuffer.len = readCount; /* wsaBuffer.buf = tsk_realloc(wsaBuffer.buf, readCount); */ } } if (ret) { ret = WSAGetLastError(); if (ret == WSAEWOULDBLOCK) { // Doesn't (always) mean congestion but... another thread is also poll()ing the FD. For example, when TURN session has a reference to the fd. TSK_DEBUG_WARN("WSAEWOULDBLOCK error for READ SSESSION"); } else if (ret == WSAECONNRESET && TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)) { /* For DGRAM ==> The sent packet gernerated "ICMP Destination/Port unreachable" result. */ TSK_FREE(wsaBuffer.buf); goto done; // ignore and retry. } else { TSK_FREE(wsaBuffer.buf); removeSocket(index, context); TNET_PRINT_LAST_ERROR("WSARecv have failed."); goto done; } } else { tnet_transport_event_t* e = tnet_transport_event_create(event_data, transport->callback_data, active_socket->fd); transport->bytes_in += wsaBuffer.len; e->data = wsaBuffer.buf; e->size = wsaBuffer.len; e->remote_addr = remote_addr; TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e); } FD_READ_DONE:; } /*================== FD_WRITE ==================*/ if (networkEvents.lNetworkEvents & FD_WRITE) { TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_WRITE", transport->description); if (networkEvents.iErrorCode[FD_WRITE_BIT]) { TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); TNET_PRINT_LAST_ERROR("WRITE FAILED."); goto done; } } /*================== FD_CLOSE ==================*/ if (networkEvents.lNetworkEvents & FD_CLOSE) { TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_CLOSE", transport->description); TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, active_socket->fd); removeSocket(index, context); } /* http://msdn.microsoft.com/en-us/library/ms741690(VS.85).aspx The proper way to reset the state of an event object used with the WSAEventSelect function is to pass the handle of the event object to the WSAEnumNetworkEvents function in the hEventObject parameter. This will reset the event object and adjust the status of active FD events on the socket in an atomic fashion. */ /* WSAResetEvent(active_event); <== DO NOT USE (see above) */ done: /* unlock context */ tsk_safeobj_unlock(context); } /* while(transport->running) */ bail: TSK_DEBUG_INFO("Stopped [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type); return tsk_null; }
TInt32 CListener::Run(TInt32 cnt) { TInt32 usedCnt = HasNewConnection(); SOCKET acceptedSocket = SOCKET_ERROR; int nLen = sizeof(SOCKADDR_IN); for (int i =0;i<usedCnt;++i) { acceptedSocket = WSAAccept(m_listeningSocket, NULL, &nLen,0,0); if (SOCKET_ERROR != acceptedSocket) { // TInt32 ret = SetSocketOptions(acceptedSocket); // if (SUCCESS > ret) // { // closesocket(ret); // continue; // } TInt32 result = SetSocketOptions(acceptedSocket); if (SUCCESS > result) { closesocket(acceptedSocket); continue; } CConnection *pNew = m_pConnectionPool->GetItem(); if (!pNew) { closesocket(acceptedSocket); return usedCnt; } CConPair pair; GetConnPair(acceptedSocket,pair); IfConnectionCallBack *pAppCallBack = m_pListenerCallBack->OnNewConnection(&pair); if (!pAppCallBack) { closesocket(acceptedSocket); continue; } IfParser *pParser; if (m_pParserFactory) { pParser = m_pParserFactory->GetParser(&pair,pNew->GetConnectionIdx()); } else { pParser = NULL; } IfCryptor *pCryptor; if (m_pCryptorFactory) { pCryptor = m_pCryptorFactory->GetCryptor(&pair,pNew->GetConnectionIdx()); } else { pCryptor = NULL; } pNew->SetConnectionType(connection_is_postive); TInt32 ret = pNew->Init(acceptedSocket,&pair,pAppCallBack,pParser,pCryptor); if (SUCCESS > ret) { pAppCallBack->OnDissconneted(ret); pNew->CloseConnection(); m_pConnectionPool->ReleaseItem(pNew); continue; } HANDLE h = CreateIoCompletionPort((HANDLE) acceptedSocket, m_compeltionPort, (ULONG_PTR)(pNew), 0); if (h != m_compeltionPort) { pAppCallBack->OnDissconneted(ret); pNew->OnDisconnected(); m_pConnectionPool->ReleaseItem(pNew); continue; } ret = pNew->OnConnected(); if (SUCCESS > ret) { pAppCallBack->OnDissconneted(ret); pNew->CloseConnection(); m_pConnectionPool->ReleaseItem(pNew); continue; } } } return usedCnt; }
void DoParent(char *pszIPAddress, char *pszPort, char *pszChildProcName) { int nFromLen; SOCKADDR_STORAGE saFrom; DWORD dwProcID; struct addrinfo hints; struct addrinfo *res; struct addrinfo *pAddr; int i; // Install the CTRL+BREAK and CTRL+C Handler if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleCtrlHandler, TRUE) == FALSE) fprintf(stderr,"SetConsoleCtrlHandler failed: %d", GetLastError()); dwProcID = GetCurrentProcessId(); printf("Parent process %lu started ...\n", dwProcID); // prepare the hints for the type of socket we are interested in. memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_protocol = IPPROTO_TCP; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; // since we're going to bind on this socket. // getaddrinfo is the protocol independent version of GetHostByName. // the res contains the result. if (getaddrinfo(pszIPAddress, pszPort, &hints, &res) != NO_ERROR) { fprintf(stderr,"getaddrinfo failed. Error = %d\n", WSAGetLastError()); goto CLEANUP; } printf("getaddrinfo successful.Enumerating the returned addresses ...\n\n"); // for each returned interface, create a listening socket. gsListen = INVALID_SOCKET; for (pAddr = res, i = 1; pAddr != NULL; pAddr = pAddr->ai_next, i++) { printf("Trying Address : %d from getaddrinfo\n", i); PrintAddressString(pAddr->ai_addr, (DWORD) pAddr->ai_addrlen); // create a suitable socket for this interface. gsListen = WSASocket(pAddr->ai_family, pAddr->ai_socktype, pAddr->ai_protocol, NULL, 0, 0); if (gsListen != INVALID_SOCKET) break; fprintf(stderr,"WSASocket failed. Error = %d\n", WSAGetLastError()); fprintf(stderr,"Ignoring this address and continuing with the next. \n\n"); } if (pAddr == NULL) { fprintf(stderr, "Couldn't find any suitable socket\n"); goto CLEANUP; } gsListen = WSASocket(pAddr->ai_family, pAddr->ai_socktype, pAddr->ai_protocol, (LPWSAPROTOCOL_INFO) NULL, 0, WSA_FLAG_OVERLAPPED); if (gsListen == INVALID_SOCKET) { fprintf(stderr, "\nWSASocket() failed to obtain the listen socket: %d\n", WSAGetLastError()); goto CLEANUP; } // bind() associates a local address and port // combination with the socket just created. if (bind(gsListen, (struct sockaddr*)pAddr->ai_addr, (int) pAddr->ai_addrlen) == SOCKET_ERROR) { fprintf(stderr, "\nbind() failed: %d\n", WSAGetLastError()); closesocket(gsListen); gsListen = INVALID_SOCKET; goto CLEANUP; } // start listening on the socket for incoming connections if (listen(gsListen,5) == SOCKET_ERROR) { fprintf(stderr, "\nlisten() failed: %d\n", WSAGetLastError()); closesocket(gsListen); gsListen = INVALID_SOCKET; goto CLEANUP; } nFromLen = sizeof(saFrom); printf("Listening on %s:%s\n", pszIPAddress? pszIPAddress : "localhost", pszPort); while(TRUE) { printf("Waiting for new connection (Type CTRL+C to exit) ...\n\n"); gsAccept = WSAAccept(gsListen, (struct sockaddr*)&saFrom, &nFromLen, (LPCONDITIONPROC)NULL, 0); if(gsAccept == INVALID_SOCKET) { fprintf(stderr, "\nWSAAccept() failed: %d\n", WSAGetLastError()); break; } // Spawn a child process to handle the I/O. DispatchChild(gsAccept, pszChildProcName); // Doing a hard shutdown here is a no-no because it // will also reset the duplicated child socket. /* LINGER lingerStruct; lingerStruct.l_onoff = 1; lingerStruct.l_linger = 0; setsockopt(gsAccept, SOL_SOCKET, SO_LINGER, (char *)&lingerStruct, sizeof(lingerStruct)); */ closesocket(gsAccept); gsAccept = INVALID_SOCKET; } CLEANUP: if (gsListen != INVALID_SOCKET) { closesocket(gsListen); gsListen = INVALID_SOCKET; } if (res != NULL) { freeaddrinfo(res); res = NULL; } }
DWORD IOCPNet::WSAAcceptProcess() { IOCPNet* pThis = this; while (true) { HANDLE_Data* hAccept = NULL; SOCKADDR_IN clientAddr; int len = sizeof(clientAddr); int acceptSocket = WSAAccept(pThis->m_ServerSocket, (sockaddr*)&clientAddr, &len, NULL, NULL); if (!m_bRun) { return 0; } if(acceptSocket == INVALID_SOCKET) { printf("create socket fail %d \n", WSAGetLastError()); /*return -1;*/ continue; } if (m_nConnectNum >= MAX_CONNECT_NUM) { closesocket(acceptSocket); printf("server has already connect full cur = %d max = %d \n", m_nConnectNum, MAX_CONNECT_NUM); continue; } hAccept = new HANDLE_Data; if (!hAccept) { closesocket(acceptSocket); printf("new HANDLE_Data fail \n"); return -1; } hAccept->acceptSocket = acceptSocket; memcpy(&hAccept->ClientAddr, &clientAddr, sizeof(SOCKADDR_IN)); pThis->m_mapClientSocket.insert(make_pair(hAccept->acceptSocket, hAccept)); printf("socket[%d] port[%d] ip[%s] connect \n", (int)hAccept->acceptSocket, hAccept->ClientAddr.sin_port, inet_ntoa(hAccept->ClientAddr.sin_addr)); HANDLE h = CreateIoCompletionPort((HANDLE)hAccept->acceptSocket, pThis->m_CompletePort, (DWORD)hAccept, 0); if (h == NULL) { closesocket(hAccept->acceptSocket); pThis->ClearClientSocket(hAccept->acceptSocket); printf("CreateIoCompletionPort fail %d \n", WSAGetLastError()); continue; } IOData* data = new IOData; if (!data) { return -1; } ZeroMemory(&data->overLapped, sizeof(data->overLapped)); data->wsaBuff.len = DataBuffSize; data->wsaBuff.buf = data->szBuffer; data->OpType = IO_TYPE_READ; DWORD RecvBytes; DWORD Flags = 0; int nError = NO_ERROR; nError = WSARecv(hAccept->acceptSocket, &data->wsaBuff, 1, &RecvBytes, &Flags, &data->overLapped, NULL); if (nError == SOCKET_ERROR) { int nError = WSAGetLastError(); if (nError != WSA_IO_PENDING ) { printf("PostIoMessage error socket=%d type=%d error=%d \n", hAccept->acceptSocket, IO_TYPE_READ, nError); } } } return 0; }
unsigned int WINAPI Proactor::ThreadProc(LPVOID lpParam) { SOCKETINFO *sInfo; int flags; int readn; Proactor *p_Pa = (Proactor*)lpParam; network *p_Net; /* initialize networking */ p_Net = Singleton<network>::getInstancePtr(); while (1) { if ((p_Net->client_fd = WSAAccept(p_Net->listen_fd, NULL, NULL, NULL, 0)) == INVALID_SOCKET) { printf("Accept Error\n"); return 1; } printf(" Accepted client fd[%d] ", p_Net->client_fd); sInfo = pClientManager->GetEmptySocketinfo(); pClientManager->PushUser(p_Net->client_fd); sInfo->fd = p_Net->client_fd; sInfo->dataBuf.len = MAX_BUFF; sInfo->dataBuf.buf = sInfo->buf; sInfo->IOOperation = ClientIoRead; /**************************/ /* CreateIoCompletionPort */ /**************************/ HANDLE check = CreateIoCompletionPort((HANDLE)p_Net->client_fd, p_Pa->g_hIOCP, (DWORD)sInfo, 0); flags = 0; if (WSARecv(sInfo->fd, &sInfo->dataBuf, 1, (DWORD *)&readn, (DWORD *)&flags, &(sInfo->overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSA_IO_PENDING) { printf("[%d] wsarecv error %d\n", __LINE__, WSAGetLastError()); } } /* 최초 반환패킷은 수신패킷 전용 스레드에서 처리하기로 #if 0 ObjectUser* pObjUser = pClientManager->FindUser(p_Net->client_fd); if (send(sInfo->fd, (char*)&pObjUser->sUser_info, sizeof(pObjUser->sUser_info), 0) == SOCKET_ERROR){ printf("Send Error\n"); } pClientManager->broadcast_success_login(sInfo->fd); #else //ObjectUser* pObjUser = pClientManager->FindUser(p_Net->client_fd); DWORD writen = 0; // return message by send socket if (WSASend(sInfo->fd, (WSABUF*)&sInfo->dataBuf, 1, (DWORD *)&writen, 0, &sInfo->overlapped, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSA_IO_PENDING) { printf("WSASend Error.. [%d] \n", WSAGetLastError()); } } #endif */ } return 1; }
int CompletionPortListener::Start() { if ((Ret = WSAStartup((2, 2), &wsaData)) != 0) { printf("WSAStartup() failed with error %d\n", Ret); return 1; } else printf("WSAStartup() is OK!\n"); // Setup an I/O completion port if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL) { printf("CreateIoCompletionPort() failed with error %d\n", GetLastError()); return 1; } else printf("CreateIoCompletionPort() is damn OK!\n"); // Determine how many processors are on the system GetSystemInfo(&SystemInfo); // Create worker threads based on the number of processors available on the // system. Create two worker threads for each processor for (i = 0; i < (int)SystemInfo.dwNumberOfProcessors * 2; i++) { // Create a server worker thread and pass the completion port to the thread if ((ThreadHandle = CreateThread(NULL, 0, ServerWorkerThread, this, 0, &ThreadID)) == NULL) { printf("CreateThread() failed with error %d\n", GetLastError()); return 1; } else printf("CreateThread() is OK!\n"); // Close the thread handle CloseHandle(ThreadHandle); } // Create a listening socket if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("WSASocket() failed with error %d\n", WSAGetLastError()); return 1; } else printf("WSASocket() is OK!\n"); InternetAddr.sin_family = AF_INET; InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY); InternetAddr.sin_port = htons(DEFAULT_PORT_INT); if (bind(Listen, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR) { printf("bind() failed with error %d\n", WSAGetLastError()); return 1; } else printf("bind() is fine!\n"); // Prepare socket for listening if (listen(Listen, 5) == SOCKET_ERROR) { printf("listen() failed with error %d\n", WSAGetLastError()); return 1; } else printf("listen() is working...\n"); completionPortStackListener.Start(); // Accept connections and assign to the completion port while (TRUE) { if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR) { printf("WSAAccept() failed with error %d\n", WSAGetLastError()); return 1; } else printf("WSAAccept() looks fine!\n"); // Create a socket information structure to associate with the socket if ((PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL) printf("GlobalAlloc() failed with error %d\n", GetLastError()); else printf("GlobalAlloc() for LPPER_HANDLE_DATA is OK!\n"); // Associate the accepted socket with the original completion port printf("Socket number %d got connected...\n", Accept); PerHandleData->Socket = Accept; if (CreateIoCompletionPort((HANDLE)Accept, CompletionPort, (DWORD)PerHandleData, 0) == NULL) { printf("CreateIoCompletionPort() failed with error %d\n", GetLastError()); return 1; } else printf("CreateIoCompletionPort() is OK!\n"); // Create per I/O socket information structure to associate with the WSARecv call below if ((PerIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA))) == NULL) { printf("GlobalAlloc() failed with error %d\n", GetLastError()); return 1; } else printf("GlobalAlloc() for LPPER_IO_OPERATION_DATA is OK!\n"); ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED)); PerIoData->BytesSEND = 0; PerIoData->BytesRECV = 0; PerIoData->DataBuf.len = DATA_BUFSIZE; PerIoData->DataBuf.buf = PerIoData->Buffer; Flags = 0; if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); return 1; } } else printf("WSARecv() is OK!\n"); } }