- CreateIoCompletionProt创建完成端口,参数为invalid_handle_value,null,0,0
- 获取系统信息,创建几个线程,绑定到上述完成端口上,
- 使用WSASocket创建socket
- 监听
- 主函数里监听连接事件,收到则用CreateIoCompletionProt将其绑定到完成端口上,并在其后为线程所用的数据开内存,因为线程重复执行,不方便在线程里面开内存
#include<iostream>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
typedef struct {
OVERLAPPED Overlapped;
WSABUF DataBuf;
char Buffer[2048];
DWORD BytesSEND;
DWORD BytesRECV;
}PER_IO_OPERATION_DATA,*LPPER_IO_OPERATION_DATA;
typedef struct {
SOCKET Socket;
}PER_HANDLE_DATA ,*LPPER_HANDLE_DATA;
DWORD WINAPI worker(LPVOID CompletionPortID) {
HANDLE CompletionPort = (HANDLE)CompletionPortID;
DWORD BytesTransferred;
LPOVERLAPPED Overlapped;
LPPER_HANDLE_DATA PerHandleData;
DWORD Flags=0;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes=0;
while (true) {
if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred
,(LPDWORD)&PerHandleData,(LPOVERLAPPED*)&PerIoData,INFINITE)==0) {
cout << "status error" << GetLastError() << endl;
return 0;
}
if (BytesTransferred == 0) {
cout << "closed socket %x" << PerHandleData->Socket << endl;
closesocket(PerHandleData->Socket);
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
}
else {
cout << PerIoData->Buffer << endl;
PerIoData->BytesRECV = 0;
Flags = 0;
ZeroMemory(&(PerIoData->Overlapped), sizeof OVERLAPPED);
PerIoData->DataBuf.len = 2048;
PerIoData->DataBuf.buf = PerIoData->Buffer;
ZeroMemory(PerIoData->Buffer, 2048);
if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1,
&RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR) {
if (WSAGetLastError() != ERROR_IO_PENDING) {
cout<<"fatal error"<<endl;
return 0;
}
}
}
}
}
int main() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "wsastart faild<<endl" << endl;
WSACleanup();
return 1;
};
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD RecvBytes=0;
DWORD Flags;
DWORD ThreadID;
if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
NULL, 0, 0)) == NULL) {
cout << "create Port failed"<<endl;
return -1;
}
GetSystemInfo(&SystemInfo);
for (int i = 0; i < SystemInfo.dwNumberOfProcessors; i++) {
HANDLE ThreadHandle;
if ((ThreadHandle = CreateThread(NULL, 0, worker, CompletionPort, 0, &ThreadID)) == NULL) {
cout << "create thread failed " << endl;
return -1;
}
CloseHandle(ThreadHandle);
}
SOCKET Listen;
if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) {
cout << "socket failed" << endl;
return -2;
}
struct sockaddr_in addr;
int addr_len = sizeof(sockaddr_in);
int port = 9901;
int errCode;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
errCode = bind(Listen, (SOCKADDR*)&addr, addr_len);
if (errCode == SOCKET_ERROR) {
cout << "bind failed" << endl;
return 1;
}
if (listen(Listen, 5) == SOCKET_ERROR) {
cout << "listen error" << endl;
exit(2);
}
SOCKET Accept;
while (1) {
if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR) {
cout << "accept error" << endl;
return -3;
}
cout << "accept " << endl;
if ((PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,
sizeof PER_HANDLE_DATA)) == NULL) {
cout<<"malloc failed"<<endl;
return -4;
}
cout << "malloc success " << endl;
PerHandleData->Socket = Accept;
if (CreateIoCompletionPort((HANDLE)Accept, CompletionPort,
(DWORD)PerHandleData, 0) == NULL) {
cout << "bind port failed" << endl;
return -4;
}
cout << "bind port success " << endl;
if ((PerIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA))) == NULL) {
cout<<"malloc failed 2"<<endl;
return -3;
}
cout << "malloc success" << endl;
ZeroMemory(PerIoData, sizeof PER_IO_OPERATION_DATA);
Flags = 0;
PerIoData->DataBuf.len = 2048;
PerIoData->DataBuf.buf = PerIoData->Buffer;
if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR) {
if (WSAGetLastError() != ERROR_IO_PENDING) {
cout << "recv error" << endl;
return -3;
}
};
}
return 0;
}