#include <winsock2.h>
#include <stdio.h>
#include <process.h>
#include <time.h>
#pragma comment(lib,"ws2_32")
#define DEFAULT_BUFLEN 1024
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DEFAULT_BUFLEN];
DWORD BytesRECV;
}PER_IO_DATA,*LPPER_IO_DATA;
typedef struct
{
SOCKET Socket;
}PER_HANDLE_DATA,*LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
int main()
{
SOCKADDR_IN InternetAddr;
SOCKET ServerSocket = INVALID_SOCKET;
SOCKET AcceptSocket = INVALID_SOCKET;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
PER_HANDLE_DATA a;
PER_IO_DATA b;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_DATA PerIoData;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret;
int iResult;
PerIoData = &b;
PerHandleData =&a;
if ((CompletionPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,8)) == NULL)
{
printf("CreateIoCompletionPort err!\n");
return -1;
}
GetSystemInfo(&SystemInfo);
for (int i=0;i<(SystemInfo.dwNumberOfProcessors)*2;i++)//创建工作线程循环
{
HANDLE ThreadHandle;
if ((ThreadHandle = CreateThread(NULL,0,ServerWorkerThread,(LPVOID)&CompletionPort,0,&ThreadID)) == NULL)
{
printf("创建工作线程i 失败");
return -1;
}
CloseHandle(ThreadHandle);
}
if ((Ret = WSAStartup(0x0202,&wsaData)) != 0)
{
printf("初始化失败");
return -1;
}
ServerSocket = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
if (ServerSocket == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n",WSAGetLastError());
return -1;
}
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr=htonl(INADDR_ANY);
InternetAddr.sin_port = htons(9000);
iResult = bind(ServerSocket,(PSOCKADDR)&InternetAddr,sizeof(InternetAddr));
if (iResult == SOCKET_ERROR)
{
printf("bind失败");
return -1;
}
if (listen(ServerSocket,5)==SOCKET_ERROR)
{
printf("listen失败");
}
printf("TCP server 开始");
sockaddr_in addrClient;
int addrClientlen = sizeof(sockaddr_in);
while (TRUE)
{
AcceptSocket = WSAAccept(ServerSocket,(sockaddr *)&addrClient,&addrClientlen,NULL,0);
if (AcceptSocket == SOCKET_ERROR)
{
printf("WSAAccept() 失败");
return -1;
}
//
PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(LPPER_HANDLE_DATA));
if (PerHandleData == NULL)
{
printf("GlobalAlloc 失败");
return -1;
}
PerHandleData->Socket =AcceptSocket;
if (CreateIoCompletionPort((HANDLE)AcceptSocket,CompletionPort,(DWORD)PerHandleData,0) == NULL)
{
printf("CreateIoCompletionPort 失败");
return -1;
}
PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));
if (PerHandleData == NULL)
{
printf("GlobalAlloc 失败");
return -1;
}
ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED));
PerIoData->BytesRECV = (DWORD)0;
PerIoData->DataBuf.len = DEFAULT_BUFLEN;
PerIoData->DataBuf.buf = PerIoData->Buffer;
Flags = 0;
iResult = WSARecv(AcceptSocket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
if (iResult == SOCKET_ERROR)
{
if (WSAGetLastError()!=ERROR_IO_PENDING)
{
printf("wsarecv 错误");
return -1;
}
}
}
return 0;
}
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = *(HANDLE*)CompletionPortID;
DWORD BytesTransferred;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_DATA PerIoData;
DWORD RecvBytes;
DWORD Flags;
int iResult;
while(true)
{
if (GetQueuedCompletionStatus(CompletionPort,&BytesTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED *)&PerIoData,INFINITE) == 0)
{
printf("GetQueuedCompletionStatus 失败");
return 0;
}
if (BytesTransferred == 0)
{
printf("Closing socket %d\n",PerHandleData->Socket);
if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("close err");
return 0;
}
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
}
if (PerIoData->BytesRECV == 0)
{
PerIoData->BytesRECV = BytesTransferred;
}
printf("\nBytes received: %d\n",BytesTransferred);
PerIoData->BytesRECV = 0;
Flags = 0;
ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DEFAULT_BUFLEN;
PerIoData->DataBuf.buf = PerIoData->Buffer;
iResult =WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
if (iResult == SOCKET_ERROR)
{
if (WSAGetLastError()!= ERROR_IO_PENDING)
{
printf("WSARecv err:%d",WSAGetLastError());
return 0;
}
}
printf("%s",PerIoData->DataBuf.buf);
return 0;
}
}