初试完成端口

本文档展示了如何使用C++和Winsock2库在Windows平台上构建一个简单的TCP服务器,该服务器利用完成端口(IOCP)进行高并发处理。代码包括了服务器的初始化、监听、接受新连接及数据接收的重叠I/O操作。
摘要由CSDN通过智能技术生成

1.完成端口写的好的博客地址

博客1
博客2

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值