- #ifdef _DEBUG
#define GMT_ASSERT(exp) assert(exp)
#else
#define GMT_ASSERT(exp)
#endifCRITICAL_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
}// whileprintf("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);