#pragma comment(lib,"ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>
//////////////////////////////////////////////////////////////////////////
// 仅供测试软件用
#define DATA_BUFSIZE 1024 // 接收缓冲区大小
typedef enum{ IOSEND,IORECV,IOQUIT } IO_TYPE;
typedef struct _SOCKET_INFORMATION {
OVERLAPPED Overlapped;
SOCKET Socket;
IO_TYPE IoType;
char buffer[DATA_BUFSIZE];
WSABUF DataBuf;
DWORD BytesSEND;
DWORD BytesRECV;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;
DWORD Flags = 0,
Bytes = 0;
DWORD WINAPI WorkThread(LPVOID CompletionPortID);
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
WSADATA wsaData;
HANDLE hCompPort;
DWORD ThreadID;
DWORD Ret;
if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
printf("WSAStartup failed with error %d
", Ret);
return FALSE;
}
if ((hCompPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
{
printf( "CreateIoCompletionPort failed with error: %d
", GetLastError());
return FALSE;
}
// 根据CPU个数来创建线程,以达到最佳性能
SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);
for(unsigned int i=0; i<SystemInfo.dwNumberOfProcessors*2; i++)
{
HANDLE ThreadHandle;
if ((ThreadHandle = CreateThread(NULL, 0, WorkThread, hCompPort, 0, &ThreadID)) == NULL)
{
printf("CreateThread() failed with error %d
", GetLastError());
return FALSE;
}
CloseHandle(ThreadHandle);
}
SOCKET ListenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED);
SOCKADDR_IN ServerAddr;
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
ServerAddr.sin_port = htons(7999);
bind(ListenSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr));
listen(ListenSocket,100);
printf("listenning...
");
SOCKADDR_IN ClientAddr;
int addr_length=sizeof(ClientAddr);
while (TRUE)
{
LPSOCKET_INFORMATION SI = new SOCKET_INFORMATION;
if ((SI->Socket = accept(ListenSocket,(SOCKADDR*)&ClientAddr, &addr_length)) != INVALID_SOCKET)
{
printf("accept ip:%s port:%d
",inet_ntoa(ClientAddr.sin_addr),ClientAddr.sin_port);
// 相关参数初始化
memset(&SI->Overlapped,0,sizeof(WSAOVERLAPPED));
memset(SI->buffer, 0, DATA_BUFSIZE);
SI->DataBuf.buf = SI->buffer;
SI->DataBuf.len = DATA_BUFSIZE;
SI->BytesRECV = 0;
SI->BytesSEND = 0;
SI->IoType = IORECV;
if (CreateIoCompletionPort((HANDLE)SI->Socket, hCompPort, (DWORD)SI, 0) == NULL)
{
printf("CreateIoCompletionPort failed with error %d
", GetLastError());
return FALSE;
}
// 发出一个重叠IO请求
if(WSARecv(SI->Socket, &SI->DataBuf, 1, &Bytes, &Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
printf("disconnect
");
closesocket(SI->Socket);
delete SI;
continue;
}
}
}
}
return FALSE;
}
DWORD WINAPI WorkThread(LPVOID CompletionPortID)
{
HANDLE hCompPort = (HANDLE)CompletionPortID;
while (TRUE)
{
DWORD BytesTransferred = 0;
LPSOCKET_INFORMATION SI = NULL;
LPWSAOVERLAPPED Overlapped = NULL;
// 线程进入线程池,等待被唤醒
if (GetQueuedCompletionStatus(hCompPort, &BytesTransferred, (LPDWORD)&SI, &Overlapped, INFINITE))
{
if (0 == BytesTransferred && IOQUIT != SI->IoType)
{
printf("disconnect
");
closesocket(SI->Socket);
delete SI;
continue;
}
switch(SI->IoType)
{
case IORECV:
{
printf("%s
", SI->buffer);
// 目前的功能是将接收到的数据原封不动的返回
SI->DataBuf.len = BytesTransferred;
SI->BytesRECV = BytesTransferred;
SI->IoType = IOSEND;
if (WSASend(SI->Socket, &SI->DataBuf, 1, &Bytes, Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
printf("disconnect
");
closesocket(SI->Socket);
delete SI;
continue;
}
}
break;
}
case IOSEND:
{
SI->BytesSEND += BytesTransferred;
//返回是否彻底,若未发完,接着发
if (SI->BytesSEND < SI->BytesRECV)
{
SI->DataBuf.buf += BytesTransferred;
SI->DataBuf.len -= BytesTransferred;
SI->IoType = IOSEND;
if (WSASend(SI->Socket, &SI->DataBuf, 1, &Bytes, Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
printf("disconnect
");
closesocket(SI->Socket);
delete SI;
continue;
}
}
}
else if (SI->BytesSEND > SI->BytesRECV)
{
printf("BytesSEND:%d > BytesRECV:%d
",SI->BytesSEND,SI->BytesRECV);
memset(SI->buffer, 0, DATA_BUFSIZE);
SI->BytesRECV = 0;
SI->BytesSEND = 0;
SI->IoType = IORECV;
SI->DataBuf.len = DATA_BUFSIZE;
SI->DataBuf.buf = SI->buffer;
}
else
{
memset(SI->buffer, 0, DATA_BUFSIZE);
SI->BytesRECV = 0;
SI->BytesSEND = 0;
SI->IoType = IORECV;
SI->DataBuf.len = DATA_BUFSIZE;
SI->DataBuf.buf = SI->buffer;
if (WSARecv(SI->Socket, &SI->DataBuf, 1, &Bytes, &Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
printf("disconnect
");
closesocket(SI->Socket);
delete SI;
continue;
}
}
}
break;
}
case IOQUIT:
{
// 让线程安全退出
return FALSE;
break;
}
default:
break;
}
}
}
return FALSE;
}
void main()
{
HANDLE hThreads = CreateThread(NULL, 0, AcceptThread, NULL, NULL, NULL);
WaitForSingleObject(hThreads,INFINITE);
printf("exit
");
CloseHandle(hThreads);
}