|
#ifdef _DEBUG #define GMT_ASSERT(exp) assert(exp) #else #define GMT_ASSERT(exp) #endif
CRITICAL_SECTION CriticalSection; LPCTSTR LPSEND_DATA = "Hello, This is GMTServer"; // Test server sending data.
#define IO_BUFSIZE 4096 * 2 // I/O buffer size. #define IP_BUFSIZE 32 // IP buffer size.
typedef enum{ IOSEND, IORECV, IOQUIT } EIO_TYPE; typedef struct _SOCKET_INFORMATION { OVERLAPPED Overlapped; SOCKET Socket; char szIOBuffer[IO_BUFSIZE]; WSABUF DataBuf; EIO_TYPE eIoType; DWORD dwIOBytes; char szIp[IP_BUFSIZE]; DWORD dwPort; _SOCKET_INFORMATION() { memset(&Overlapped,0,sizeof(WSAOVERLAPPED)); memset(szIOBuffer, 0, sizeof(szIOBuffer)); DataBuf.buf = szIOBuffer; DataBuf.len = sizeof(szIOBuffer) - 1; eIoType = IOQUIT; dwIOBytes = 0; memset(szIp, 0, sizeof(szIp)); dwPort = 0; } } SOCKET_INFORMATION, * LPSOCKET_INFORMATION;
HANDLE g_hCompletePort = NULL; SOCKET g_ListenSocket = NULL; // Listenning socket. unsigned __stdcall IOThread(LPVOID pArguments);
// Deliver send operation. // @ret 0 success or error code. int SendData(LPSOCKET_INFORMATION lpSI) { if (NULL == lpSI) return -1;
if (INVALID_SOCKET == lpSI->Socket) return -1;
int nRet = 0; DWORD dwFlags = 0; lpSI->dwIOBytes = 0; strcpy(lpSI->szIOBuffer, LPSEND_DATA); lpSI->DataBuf.buf = lpSI->szIOBuffer; lpSI->DataBuf.len = strlen(lpSI->szIOBuffer); lpSI->eIoType = IOSEND; if (WSASend(lpSI->Socket, &(lpSI->DataBuf), 1, &lpSI->dwIOBytes, dwFlags, &(lpSI->Overlapped), NULL) == SOCKET_ERROR) { nRet = WSAGetLastError(); if (nRet != ERROR_IO_PENDING) { printf("WSASend() failed with error %d/n", nRet); if (0 == closesocket(lpSI->Socket)) { lpSI->Socket = INVALID_SOCKET; delete lpSI; lpSI = NULL; } } else nRet = 0; }
return nRet; }
// Deliver recv operation. // @ret 0 success or error code. int RecvData(LPSOCKET_INFORMATION lpSI) { if (NULL == lpSI) return -1;
if (INVALID_SOCKET == lpSI->Socket) return -1;
int nRet = 0; DWORD dwFlags = 0; lpSI->eIoType = IORECV; memset(lpSI->szIOBuffer, 0, sizeof(lpSI->szIOBuffer)); lpSI->DataBuf.len = sizeof(lpSI->szIOBuffer) - 1; lpSI->DataBuf.buf = lpSI->szIOBuffer; if (WSARecv(lpSI->Socket, &(lpSI->DataBuf), 1, &lpSI->dwIOBytes, &dwFlags, &(lpSI->Overlapped), NULL) == SOCKET_ERROR) { nRet = WSAGetLastError(); if (nRet != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d/n", nRet);
if (0 == closesocket(lpSI->Socket)) { lpSI->Socket = INVALID_SOCKET; delete lpSI; lpSI = NULL; } } else nRet = 0; }
return nRet; }
unsigned __stdcall IOThread(LPVOID lpArg) { int nRet; DWORD dwFlags; DWORD dwBytesTransferred = 0; LPSOCKET_INFORMATION lpSI = NULL; LPWSAOVERLAPPED lpOverlapped = NULL; while (TRUE) { //线程进入线程池,等待被唤醒 lpSI = NULL; lpOverlapped = NULL; nRet = GetQueuedCompletionStatus(g_hCompletePort, &dwBytesTransferred, (PULONG_PTR)&lpSI, &lpOverlapped, INFINITE); if (nRet == 0 || dwBytesTransferred == 0) { if (closesocket(lpSI->Socket) == 0) { printf("GetQueuedCompletionStatus failed with error %d/n", GetLastError()); lpSI->Socket = INVALID_SOCKET; delete lpSI; lpSI = NULL; }
continue; }
GMT_ASSERT(NULL != lpSI); lpSI->dwIOBytes = dwBytesTransferred;
switch(lpSI->eIoType) { case IORECV: { EnterCriticalSection(&CriticalSection);
// 输出代表数据处理 printf("[%s:%d][%d]%s/n", lpSI->szIp, lpSI->dwPort, dwBytesTransferred, lpSI->szIOBuffer); // Sleep(4000); //模拟处理时间
LeaveCriticalSection(&CriticalSection);
if (0 != SendData(lpSI)) return 1;
break; } case IOSEND: { if (0 != RecvData(lpSI)) return 1; break; } case IOQUIT: default: break; }// switch }// while
printf("IOThread is over/r/n"); return 0; }
// Listen ... // @ret 0 success or error code int Listen(LPCTSTR lpServerIp, DWORD dwPort) { DWORD dwErr = 0; WSADATA wsaData; DWORD nRet = 0; nRet = WSAStartup(0x0202, &wsaData); if (nRet != 0) { printf("WSAStartup failed with error %d/n", nRet); return nRet; }
InitializeCriticalSection(&CriticalSection);
g_hCompletePort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (NULL == g_hCompletePort) { dwErr = WSAGetLastError(); printf("CreateIoCompletionPort failed with error %d", dwErr); WSACleanup(); return dwErr; }
//根据2倍于CPU个数+2来创建线程,以达到系统最佳性能 SYSTEM_INFO SystemInfo; GetSystemInfo(&SystemInfo); unsigned threadID; for(unsigned int i=0; i<SystemInfo.dwNumberOfProcessors * 2+2; i++) { HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0, &IOThread, NULL, 0, &threadID); if (hThread == NULL) { dwErr = GetLastError(); printf("Create IOThread failed with error %d", dwErr); return dwErr; } CloseHandle(hThread); }
g_ListenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED); if (INVALID_SOCKET == g_ListenSocket) { dwErr = WSAGetLastError(); printf("WSASocket failed with error %d", dwErr); WSACleanup(); return dwErr; }
SOCKADDR_IN ServerAddr; memset(&ServerAddr, 0, sizeof(SOCKADDR_IN)); ServerAddr.sin_family = AF_INET; if (lpServerIp == NULL) ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); else ServerAddr.sin_addr.S_un.S_addr = inet_addr(lpServerIp); ServerAddr.sin_port = htons(dwPort); if (SOCKET_ERROR == bind(g_ListenSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr))) { dwErr = WSAGetLastError(); printf("bind failed with error %d", dwErr); WSACleanup(); return dwErr; }
if (SOCKET_ERROR == listen(g_ListenSocket, SOMAXCONN)) { dwErr = WSAGetLastError(); printf("listen failed with error %d", dwErr); WSACleanup(); return dwErr; }
printf("listenning.../n");
// Accept connections and assign to the completion port. SOCKET AcceptSocket; while(TRUE) { printf("waiting for client connect./r/n");
SOCKADDR_IN saClient; int nLen = sizeof(SOCKADDR_IN); memset(&saClient, 0, sizeof(SOCKADDR_IN)); AcceptSocket = INVALID_SOCKET; AcceptSocket = WSAAccept(g_ListenSocket, (sockaddr *)&saClient, &nLen, NULL, 0); if (INVALID_SOCKET == AcceptSocket) { printf("WSAAccept() failed with error %d/n", WSAGetLastError()); dwErr = WSAGetLastError(); break; }
// Associate the accepted socket with the original completion port. LPSOCKET_INFORMATION pSI = new SOCKET_INFORMATION; pSI->Socket = AcceptSocket; strcpy(pSI->szIp, inet_ntoa(saClient.sin_addr)); pSI->dwPort = saClient.sin_port; if (CreateIoCompletionPort((HANDLE) AcceptSocket, g_hCompletePort, (DWORD)pSI, 0) == NULL) { printf("CreateIoCompletionPort failed with error %d/n", GetLastError()); dwErr = WSAGetLastError(); break; }
dwErr = RecvData(pSI); if (0 != dwErr) break; //Deliver recv operation. }
DeleteCriticalSection(&CriticalSection);
WSACleanup();
printf("The main thread is over./n");
return dwErr; }
// Set sending file and recving file, listen ip and port. // @para lpSendFile send file path, not use temporarily. // lpRecvFile recv file path, not use temporarily. // lpServerIp NULL any ip or specified ip. // dwPort listen port. // dwSenInterval send operation time interval, not use temporarily. // dwRecvInterval Recv operation time interval, not use temporarily. // // @ret 0 success or error code. CMPLTIOSERVER_API int SetServer(LPCTSTR lpSendFile, LPCTSTR lpRecvFile, LPCTSTR lpServerIp, DWORD dwPort, DWORD dwSenInterval, DWORD dwRecvInternal) { return Listen(lpServerIp, dwPort); }
// using PFUN pfun; HINSTANCE dllmodule = NULL; dllmodule=LoadLibrary("CmpltIOServer.dll"); pfun=(PFUN)GetProcAddress(dllmodule,"SetServer"); if (NULL == pfun) { DWORD dwErr = GetLastError(); cout << "error code:" << dwErr << endl; return 1; }
int nRet = pfun(NULL, NULL, g_szServer, g_dwPort, 2000, 4000);
FreeLibrary(dllmodule);
|