#include <WinSock2.h>
#include <Windows.h>
#include <vector>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib") //socket动态链接库
#pragma comment(lib, "kernel32.lib") //IOCP动态链接库
//重叠IO用到的结构体,记录IO数据
const int DataBufferSize = 2* 1024;
typedef struct s1
{
OVERLAPPED overlapped;
WSABUF databuff;
char cBuffer[DataBufferSize];
int BufferLen;
int OperationType;
}PER_IO_DATA, *LPPER_IO_DATA;
//记录每个连接的socket信息
typedef struct
{
SOCKET socket;
SOCKADDR_STORAGE clientAddr;
}PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
//定义全局变量
const int nDefaultPort = 6000;
vector<PER_HANDLE_DATA *> g_vClientGroup;//记录客户端的容器
HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
DWORD WINAPI ServerWorkThread(LPVOID CompletionPortID);
DWORD WINAPI ServerSendThread(LPVOID lpParam);
int main()
{
WORD wVersionRequested = MAKEWORD(2,2);//请求版本为2.2的WINSOCKET库
WSADATA wsaData; //接收windows socket的结构信息
DWORD err = WSAStartup(wVersionRequested, &wsaData);
if(0 != err)
{
cout<<"Request Windows Socket Library Error!"<<endl;
return -1;
}
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
WSACleanup();
cout<<"Request Windows Socket Version 2.2 Error!"<<endl;
return -1;
}
//创建IOCP的内核对象
HANDLE completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if(NULL == completionPort)
{
cout<<"CreateIoCompletionPort failed Error!"<<GetLastError()<<endl;
return -1;
}
//创建处理器的核心数量
SYSTEM_INFO mySysInfo;
GetSystemInfo(&mySysInfo);
//创建工作线程
for(DWORD i = 0; i < (mySysInfo.dwNumberOfProcessors * 2); i++)
{
HANDLE ThreadHandle = CreateThread(NULL, 0, ServerWorkThread, completionPort, 0, NULL);
if(NULL == ThreadHandle)
{
cout<<"Create Thread Handle failed Error:"<<GetLastError()<<endl;
return -1;
}
CloseHandle(ThreadHandle);
}
//建立服务器套接字
SOCKET srvSocket = socket(AF_INET, SOCK_STREAM, 0);
//绑定SOCKET到本机
SOCKADDR_IN srvAddr;
srvAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
srvAddr.sin_family = AF_INET;
srvAddr.sin_port = htons(nDefaultPort);
int nBindResult = bind(srvSocket, (SOCKADDR *)&srvAddr, sizeof(SOCKADDR));
if(SOCKET_ERROR == nBindResult)
{
cout<<"Bind failed Error:"<<GetLastError()<<endl;
return -1;
}
//将socket设置为监听模式
int nListenResult = listen(srvSocket, SOMAXCONN);
if(SOCKET_ERROR == nListenResult)
{
cout<<"Listen failed Error:"<<GetLastError()<<endl;
return -1;
}
cout<<"服务器已启动,等待客户端连接..."<<endl;
//创建用于发送数据的线程
HANDLE sendThread = CreateThread(NULL, 0, ServerSendThread, 0, 0, NULL);
while(true)
{
PER_HANDLE_DATA * lpPer_Handle_Data = NULL;
SOCKADDR_IN sockaddr_client;
int nsocketaddr_client;
SOCKET acceptSocket;
nsocketaddr_client = sizeof(sockaddr_client);
acceptSocket = accept(srvSocket, (sockaddr *)&sockaddr_client, &nsocketaddr_client);
if(SOCKET_ERROR == acceptSocket)
{
cout<<"Accept Socket Error:"<<GetLastError()<<endl;
return -1;
}
//创建用来和套接字关联的单句柄数据信息结构
lpPer_Handle_Data = new PER_HANDLE_DATA;
lpPer_Handle_Data->socket = acceptSocket;
memcpy(&lpPer_Handle_Data->clientAddr, &sockaddr_client, nsocketaddr_client);
g_vClientGroup.push_back(lpPer_Handle_Data);
//将接收套接字和完成端口关联
CreateIoCompletionPort((HANDLE)(lpPer_Handle_Data->socket), completionPort, (DWORD)lpPer_Handle_Data, 0);
LPPER_IO_DATA perIoData = NULL;
memset(perIoData, 0, sizeof(struct s1));
//perIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_DATA));
//perIoData = new PER_IO_DATA;
//ZeroMemory(&(perIoData->overlapped), sizeof(OVERLAPPED));
perIoData->databuff.len = 1024;
perIoData->databuff.buf = perIoData->cBuffer;
perIoData->OperationType = 0; //read
DWORD RecvBytes;
DWORD Flags = 0;
WSARecv(lpPer_Handle_Data->socket, &(perIoData->databuff), 1, &RecvBytes, &Flags, &(perIoData->overlapped), NULL);
}
return 0;
}
//开始服务器工作线程函数
DWORD WINAPI ServerWorkThread(LPVOID IpParam)
{
HANDLE CompletionPort = (HANDLE)IpParam;
DWORD BytesTransferred;
LPOVERLAPPED IpOverlapped;
LPPER_HANDLE_DATA PerHandleData = NULL;
LPPER_IO_DATA lpPerIoData = NULL;
DWORD RecvBytes;
DWORD Flags = 0;
BOOL bRet = false;
while(true)
{
bRet = GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (PULONG_PTR)&PerHandleData, (LPOVERLAPPED *)&IpOverlapped, INFINITE);
if(bRet == 0)
{
cout<<"GetQueuedCompletionStatus Error:"<<GetLastError()<<endl;
return -1;
}
lpPerIoData = (LPPER_IO_DATA)CONTAINING_RECORD(IpOverlapped, PER_IO_DATA, overlapped);
if(0 == BytesTransferred)
{
closesocket(PerHandleData->socket);
GlobalFree(PerHandleData);
GlobalFree(lpPerIoData);
continue;
}
//开始数据处理,接收来至客户端的数据
WaitForSingleObject(hMutex, INFINITE);
cout<<"A Client says:"<<lpPerIoData->databuff.buf<<endl;
ReleaseMutex(hMutex);
//为下一个重叠调用建立单I/O操作数据
ZeroMemory(&(lpPerIoData->overlapped), sizeof(OVERLAPPED)); //清空内存
lpPerIoData->databuff.len = 1024;
lpPerIoData->databuff.buf = lpPerIoData->cBuffer;
lpPerIoData->OperationType = 0;
WSARecv(PerHandleData->socket, &(lpPerIoData->databuff), 1, &RecvBytes, &Flags, &(lpPerIoData->overlapped), NULL);
}
return 0;
}
DWORD WINAPI ServerSendThread(LPVOID IpParam)
{
while(true)
{
char talk[200]={0x00};
gets(talk);
int len;
for(len=0; talk[len] != '\0'; ++len)
{
}
talk[len]='\n';
talk[++len] = '\0';
cout<<"I Say :";
cout<<talk<<endl;
WaitForSingleObject(hMutex, INFINITE);
for(int i=0; i<g_vClientGroup.size(); i++)
{
send(g_vClientGroup[i]->socket, talk, 200, 0);
}
ReleaseMutex(hMutex);
}
return 0;
}