1.完成端口写的好的博客地址
2.简易服务器实现代码
#include <iostream>
#include <winsock2.h>
#include <ws2def.h>
using namespace std;
#define MAX_SIZE 1024
#define LISTEN_SOCK_PORT 5060
#pragma comment( lib, "ws2_32.lib" )
//代表参数完成键 CompletionPort
typedef struct
{
SOCKET sock;
sockaddr_in ClientSockInfo;
}CLIENT_SOCK_INFO_KEY;
//代表GetQueuedCompletionStatus第四个参数
typedef struct
{
OVERLAPPED overlapped; //重叠结构
WSABUF buf;
char szBuf[MAX_SIZE]; //buf 的缓冲区
DWORD NumberOfBytesRecvd; //指定接收到的字符的数目
DWORD Flags;
}MY_OVERLAPPED, *LPMY_OVERLAPPED;
DWORD WINAPI WorkerThread(LPVOID lpParameter);
int main()
{
WSADATA wd;
if (0 != WSAStartup(MAKEWORD(2, 2,), &wd))
{
cerr << "WSAStartup " << endl;
exit(-1);
}
//建立重叠结构的监听socket
SOCKET ListenSocket =
WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
WSA_FLAG_OVERLAPPED);
//对socket进行相关设置
sockaddr_in ListenSockInfo;
ListenSockInfo.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
ListenSockInfo.sin_family = AF_INET;
ListenSockInfo.sin_port = htons(LISTEN_SOCK_PORT);
if (0 != bind(ListenSocket, (SOCKADDR*)&ListenSockInfo, sizeof(sockaddr_in)))
{
closesocket(ListenSocket);
WSACleanup();
cerr << "bind " << endl;
exit(-1);
}
if (0 != listen(ListenSocket, 10))
{
closesocket(ListenSocket);
WSACleanup();
cerr << "listen " << endl;
exit(-1);
}
//创建一个新的完成端口
HANDLE port =
CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
if (NULL == port)
{
perror("CreateIoCompletionPort(): ");
WSACleanup();
exit(-1);
}
SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
int MaxThread = SysInfo.dwNumberOfProcessors * 2;
//创建线程为完成端口服务
for (int i = 0; i < MaxThread; i++)
{
CreateThread(NULL, NULL, WorkerThread, port, NULL, NULL);
}
sockaddr_in ClientInfo;
int SockSize = sizeof(sockaddr_in);
while (true)
{
SOCKET NewSock =
accept(ListenSocket, (SOCKADDR*)&ClientInfo, &SockSize);
//填写完成端口中的完成键信息
CLIENT_SOCK_INFO_KEY* pClientInfo =
(CLIENT_SOCK_INFO_KEY*)malloc( sizeof(CLIENT_SOCK_INFO_KEY));
pClientInfo->sock = NewSock;
memcpy(&pClientInfo->ClientSockInfo, &ClientInfo, SockSize);
LPMY_OVERLAPPED pOverlapp = (LPMY_OVERLAPPED)malloc(sizeof(MY_OVERLAPPED));
ZeroMemory(pOverlapp, sizeof(MY_OVERLAPPED));
pOverlapp->buf.buf = pOverlapp->szBuf;
pOverlapp->buf.len = MAX_SIZE;
//将新建立的套接字 与完成端口 进行绑定
CreateIoCompletionPort((HANDLE)NewSock, port,
(u_long)pClientInfo, 0);
//为新建立的套接字 投递接受请求
WSARecv(NewSock, &pOverlapp->buf, 1,
&pOverlapp->NumberOfBytesRecvd,
&pOverlapp->Flags, &pOverlapp->overlapped,NULL);
}
WSACleanup();
return 0;
}
DWORD WINAPI WorkerThread(LPVOID lpParameter)
{
HANDLE port = lpParameter;
DWORD BytesTransfer;
CLIENT_SOCK_INFO_KEY* pKey;
LPMY_OVERLAPPED pOver;
while (1)
{
GetQueuedCompletionStatus(port, &BytesTransfer,
(LPDWORD)&pKey, (LPOVERLAPPED*)&pOver, INFINITE);
//如果接收到的字节数是0的话,那么就证明该客户端已经断开连接了
//此时需要对分配的完成键和重叠结构进行释放
if (0 >= BytesTransfer)
{
delete pKey;
delete pOver;
continue;
}
cout << pOver->szBuf << endl;
//为重新投递一个请求
WSARecv(pKey->sock, &pOver->buf, 1,
&pOver->NumberOfBytesRecvd, &pOver->Flags,
&pOver->overlapped, NULL);
}
return TRUE;
}
版权声明:本文为ZZHinclude原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。