简单的IOCP例子

使用IOCP模型编程的优点 
① 帮助维持重复使用的内存池。(与重叠I/O技术有关) 
② 去除删除线程创建/终结负担。 
③ 利于管理,分配线程,控制并发,最小化的线程上下文切换。 
④ 优化线程调度,提高CPU和内存缓冲的命中率。 
服务器:

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// IOCP_TCPIP_Socket_Server.cpp</span>

<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <WinSock2.h></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <Windows.h></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <vector></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span>


<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>;

<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma comment(lib, "Ws2_32.lib")      <span class="hljs-comment" style="box-sizing: border-box;">// Socket编程需用的动态链接库</span></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma comment(lib, "Kernel32.lib")    <span class="hljs-comment" style="box-sizing: border-box;">// IOCP需要用到的动态链接库</span></span>

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
* 结构体名称:PER_IO_DATA
* 结构体功能:重叠I/O需要用到的结构体,临时记录IO数据
**/</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> DataBuffSize = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1024</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span>
{
    OVERLAPPED overlapped;
    WSABUF databuff;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> buffer[DataBuffSize];
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> BufferLen;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> operationType;
}PER_IO_OPERATEION_DATA, *LPPER_IO_OPERATION_DATA, *LPPER_IO_DATA, PER_IO_DATA;

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
* 结构体名称:PER_HANDLE_DATA
* 结构体存储:记录单个套接字的数据,包括了套接字的变量及套接字的对应的客户端的地址。
* 结构体作用:当服务器连接上客户端时,信息存储到该结构体中,知道客户端的地址以便于回访。
**/</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span>
{
    SOCKET socket;
    SOCKADDR_STORAGE ClientAddr;
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 定义全局变量</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> DefaultPort = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5000</span>;
<span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span> < PER_HANDLE_DATA* ></span> clientGroup;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 记录客户端的向量组</span>
<span class="hljs-stl_container" style="box-sizing: border-box;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">vector</span><LPPER_IO_OPERATION_DATA></span> IOOperationDataGroup;

HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
DWORD WINAPI ServerWorkThread(LPVOID CompletionPortID);
DWORD WINAPI ServerSendThread(LPVOID IpParam);

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 开始主函数</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main()
{
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 加载socket动态链接库</span>
    WORD wVersionRequested = MAKEWORD(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 请求2.2版本的WinSock库</span>
    WSADATA wsaData;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 接收Windows Socket的结构信息</span>
    DWORD err = WSAStartup(wVersionRequested, &wsaData);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> != err) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 检查套接字库是否申请成功</span>
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cerr</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Request Windows Socket Library Error!\n"</span>;
        system(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"pause"</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
    }
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (LOBYTE(wsaData.wVersion) != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> || HIBYTE(wsaData.wVersion) != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>) {<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 检查是否申请了所需版本的套接字库</span>
        WSACleanup();
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cerr</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Request Windows Socket Version 2.2 Error!\n"</span>;
        system(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"pause"</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建IOCP的内核对象</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
    * 需要用到的函数的原型:
    * HANDLE WINAPI CreateIoCompletionPort(
    *    __in   HANDLE FileHandle,      // 已经打开的文件句柄或者空句柄,一般是客户端的句柄
    *    __in   HANDLE ExistingCompletionPort,  // 已经存在的IOCP句柄
    *    __in   ULONG_PTR CompletionKey,    // 完成键,包含了指定I/O完成包的指定文件
    *    __in   DWORD NumberOfConcurrentThreads // 真正并发同时执行最大线程数,一般推介是CPU核心数*2
    * );
    **/</span>
    HANDLE completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (NULL == completionPort) {   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建IO内核对象失败</span>
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cerr</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CreateIoCompletionPort failed. Error:"</span> << GetLastError() << endl;
        system(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"pause"</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建IOCP线程--线程里面创建线程池</span>

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 确定处理器的核心数量</span>
    SYSTEM_INFO mySysInfo;
    GetSystemInfo(&mySysInfo);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 基于处理器的核心数量创建线程</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (DWORD i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < (mySysInfo.dwNumberOfProcessors * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>); ++i) {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建服务器工作器线程,并将完成端口传递到该线程</span>
        HANDLE ThreadHandle = CreateThread(NULL, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, ServerWorkThread, completionPort, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, NULL);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第一NULL代表默认安全选项,第一个0,代表线程占用资源大小,第二个0,代表线程创建后立即执行</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (NULL == ThreadHandle) {
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cerr</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Create Thread Handle failed. Error:"</span> << GetLastError() << endl;
            system(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"pause"</span>);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
        }
        CloseHandle(ThreadHandle);
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 建立流式套接字</span>
    SOCKET srvSocket = socket(AF_INET, SOCK_STREAM, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 绑定SOCKET到本机</span>
    SOCKADDR_IN srvAddr;
    srvAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    srvAddr.sin_family = AF_INET;
    srvAddr.sin_port = htons(DefaultPort);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> bindResult = bind(srvSocket, (SOCKADDR*)&srvAddr, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(SOCKADDR));
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (SOCKET_ERROR == bindResult) {
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cerr</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Bind failed. Error:"</span> << GetLastError() << endl;
        system(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"pause"</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 将SOCKET设置为监听模式</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> listenResult = listen(srvSocket, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (SOCKET_ERROR == listenResult) {
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cerr</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Listen failed. Error: "</span> << GetLastError() << endl;
        system(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"pause"</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 开始处理IO数据</span>
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"本服务器已准备就绪,正在等待客户端的接入...\n"</span>;

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"> 创建用于发送数据的线程</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//HANDLE sendThread = CreateThread(NULL, 0, ServerSendThread, 0, 0, NULL);//第二个0,代表回掉函数参数为0</span>

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>) {
        PER_HANDLE_DATA * PerHandleData = NULL;
        SOCKADDR_IN saRemote;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> RemoteLen;
        SOCKET acceptSocket;

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 接收连接,并分配完成端,这儿可以用AcceptEx()</span>
        RemoteLen = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(saRemote);
        acceptSocket = accept(srvSocket, (SOCKADDR*)&saRemote, &RemoteLen);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (SOCKET_ERROR == acceptSocket) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 接收客户端失败</span>
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cerr</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Accept Socket Error: "</span> << GetLastError() << endl;
            system(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"pause"</span>);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建用来和套接字关联的单句柄数据信息结构</span>
        PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(PER_HANDLE_DATA));  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 在堆中为这个PerHandleData申请指定大小的内存</span>
        PerHandleData->socket = acceptSocket;
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">memcpy</span>(&PerHandleData->ClientAddr, &saRemote, RemoteLen);
        clientGroup.push_back(PerHandleData);       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 将单个客户端数据指针放到客户端组中</span>

                                                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 将接受套接字和完成端口关联</span>
        CreateIoCompletionPort((HANDLE)(PerHandleData->socket), completionPort, (DWORD)PerHandleData, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);


        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 开始在接受套接字上处理I/O使用重叠I/O机制</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 在新建的套接字上投递一个或多个异步</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// WSARecv或WSASend请求,这些I/O请求完成后,工作者线程会为I/O请求提供服务    </span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 单I/O操作数据(I/O重叠)</span>
        LPPER_IO_OPERATION_DATA PerIoData = NULL;
        PerIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(PER_IO_OPERATEION_DATA));
        ZeroMemory(&(PerIoData->overlapped), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(OVERLAPPED));
        PerIoData->databuff.len = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1024</span>;
        PerIoData->databuff.buf = PerIoData->buffer;
        PerIoData->operationType = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// read</span>

        IOOperationDataGroup.push_back(PerIoData);

        DWORD RecvBytes;
        DWORD Flags = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//WSARecv中的1,代表缓冲区lpBuffers只包含一个WSABUF,Flags代表接收普通数据</span>
        WSARecv(PerHandleData->socket, &(PerIoData->databuff), <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, &RecvBytes, &Flags, &(PerIoData->overlapped), NULL);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//PerIoData->overlapped就是CONTAINING_RECORD的第一个变量</span>
    }


    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">auto</span> it = IOOperationDataGroup.begin(); it != IOOperationDataGroup.end(); it++)
    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (*it != NULL)
            GlobalFree(*it);
    }

    system(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"pause"</span>);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 开始服务工作线程函数</span>
DWORD WINAPI ServerWorkThread(LPVOID IpParam)
{
    HANDLE CompletionPort = (HANDLE)IpParam;
    DWORD BytesTransferred;
    LPOVERLAPPED IpOverlapped;
    LPPER_HANDLE_DATA PerHandleData = NULL;
    LPPER_IO_DATA PerIoData = NULL;
    DWORD RecvBytes;
    DWORD Flags = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    BOOL bRet = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>) {
        bRet = GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (PULONG_PTR)&PerHandleData, (LPOVERLAPPED*)&IpOverlapped, INFINITE);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//此处可以将IpOverlapped换为PerIoData,然后将下面CONTAINING_RECORD注释掉</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (bRet == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cerr</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"GetQueuedCompletionStatus Error: "</span> << GetLastError() << endl;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
        }
        PerIoData = (LPPER_IO_DATA)CONTAINING_RECORD(IpOverlapped, PER_IO_DATA, overlapped);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这个宏的作用是:根据一个结构体实例中的成员的地址,取到整个结构体实例的地址</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//PER_IO_DATA的成员overlapped的地址为&IpOverlapped,结果就可以获得PER_IO_DATA的地址</span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 检查在套接字上是否有错误发生</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> == BytesTransferred) {
            closesocket(PerHandleData->socket);
            GlobalFree(PerHandleData);
            GlobalFree(PerIoData);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">continue</span>;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 开始数据处理,接收来自客户端的数据</span>
        WaitForSingleObject(hMutex, INFINITE);
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"A Client says: "</span> << PerIoData->databuff.buf << endl;
        ReleaseMutex(hMutex);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 为下一个重叠调用建立单I/O操作数据</span>
        ZeroMemory(&(PerIoData->overlapped), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(OVERLAPPED)); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 清空内存</span>
        PerIoData->databuff.len = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1024</span>;
        PerIoData->databuff.buf = PerIoData->buffer;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//buf是个指针,这一过程会清空buffer的内容</span>
        PerIoData->operationType = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// read</span>
        WSARecv(PerHandleData->socket, &(PerIoData->databuff), <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, &RecvBytes, &Flags, &(PerIoData->overlapped), NULL);
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}


<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 发送信息的线程执行函数</span>
DWORD WINAPI ServerSendThread(LPVOID IpParam)
{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (clientGroup.empty())
        {
            Sleep(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5000</span>);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">continue</span>;
        }

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> talk[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>];
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cin</span>.get(talk,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> len;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (len = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; talk[len] != <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\0'</span>; ++len) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 找出这个字符组的长度</span>
        }
        talk[len] = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\n'</span>;
        talk[++len] = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\0'</span>;
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"I Say:"</span>);
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << talk;
        WaitForSingleObject(hMutex, INFINITE);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < clientGroup.size(); ++i) {
            send(clientGroup[i]->socket, talk, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 发送信息</span>
        }
        ReleaseMutex(hMutex);
    }
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li><li style="box-sizing: border-box; padding: 0px 5px;">174</li><li style="box-sizing: border-box; padding: 0px 5px;">175</li><li style="box-sizing: border-box; padding: 0px 5px;">176</li><li style="box-sizing: border-box; padding: 0px 5px;">177</li><li style="box-sizing: border-box; padding: 0px 5px;">178</li><li style="box-sizing: border-box; padding: 0px 5px;">179</li><li style="box-sizing: border-box; padding: 0px 5px;">180</li><li style="box-sizing: border-box; padding: 0px 5px;">181</li><li style="box-sizing: border-box; padding: 0px 5px;">182</li><li style="box-sizing: border-box; padding: 0px 5px;">183</li><li style="box-sizing: border-box; padding: 0px 5px;">184</li><li style="box-sizing: border-box; padding: 0px 5px;">185</li><li style="box-sizing: border-box; padding: 0px 5px;">186</li><li style="box-sizing: border-box; padding: 0px 5px;">187</li><li style="box-sizing: border-box; padding: 0px 5px;">188</li><li style="box-sizing: border-box; padding: 0px 5px;">189</li><li style="box-sizing: border-box; padding: 0px 5px;">190</li><li style="box-sizing: border-box; padding: 0px 5px;">191</li><li style="box-sizing: border-box; padding: 0px 5px;">192</li><li style="box-sizing: border-box; padding: 0px 5px;">193</li><li style="box-sizing: border-box; padding: 0px 5px;">194</li><li style="box-sizing: border-box; padding: 0px 5px;">195</li><li style="box-sizing: border-box; padding: 0px 5px;">196</li><li style="box-sizing: border-box; padding: 0px 5px;">197</li><li style="box-sizing: border-box; padding: 0px 5px;">198</li><li style="box-sizing: border-box; padding: 0px 5px;">199</li><li style="box-sizing: border-box; padding: 0px 5px;">200</li><li style="box-sizing: border-box; padding: 0px 5px;">201</li><li style="box-sizing: border-box; padding: 0px 5px;">202</li><li style="box-sizing: border-box; padding: 0px 5px;">203</li><li style="box-sizing: border-box; padding: 0px 5px;">204</li><li style="box-sizing: border-box; padding: 0px 5px;">205</li><li style="box-sizing: border-box; padding: 0px 5px;">206</li><li style="box-sizing: border-box; padding: 0px 5px;">207</li><li style="box-sizing: border-box; padding: 0px 5px;">208</li><li style="box-sizing: border-box; padding: 0px 5px;">209</li><li style="box-sizing: border-box; padding: 0px 5px;">210</li><li style="box-sizing: border-box; padding: 0px 5px;">211</li><li style="box-sizing: border-box; padding: 0px 5px;">212</li><li style="box-sizing: border-box; padding: 0px 5px;">213</li><li style="box-sizing: border-box; padding: 0px 5px;">214</li><li style="box-sizing: border-box; padding: 0px 5px;">215</li><li style="box-sizing: border-box; padding: 0px 5px;">216</li><li style="box-sizing: border-box; padding: 0px 5px;">217</li><li style="box-sizing: border-box; padding: 0px 5px;">218</li><li style="box-sizing: border-box; padding: 0px 5px;">219</li><li style="box-sizing: border-box; padding: 0px 5px;">220</li><li style="box-sizing: border-box; padding: 0px 5px;">221</li><li style="box-sizing: border-box; padding: 0px 5px;">222</li><li style="box-sizing: border-box; padding: 0px 5px;">223</li><li style="box-sizing: border-box; padding: 0px 5px;">224</li><li style="box-sizing: border-box; padding: 0px 5px;">225</li><li style="box-sizing: border-box; padding: 0px 5px;">226</li><li style="box-sizing: border-box; padding: 0px 5px;">227</li><li style="box-sizing: border-box; padding: 0px 5px;">228</li><li style="box-sizing: border-box; padding: 0px 5px;">229</li><li style="box-sizing: border-box; padding: 0px 5px;">230</li><li style="box-sizing: border-box; padding: 0px 5px;">231</li><li style="box-sizing: border-box; padding: 0px 5px;">232</li><li style="box-sizing: border-box; padding: 0px 5px;">233</li><li style="box-sizing: border-box; padding: 0px 5px;">234</li><li style="box-sizing: border-box; padding: 0px 5px;">235</li><li style="box-sizing: border-box; padding: 0px 5px;">236</li><li style="box-sizing: border-box; padding: 0px 5px;">237</li><li style="box-sizing: border-box; padding: 0px 5px;">238</li><li style="box-sizing: border-box; padding: 0px 5px;">239</li><li style="box-sizing: border-box; padding: 0px 5px;">240</li><li style="box-sizing: border-box; padding: 0px 5px;">241</li><li style="box-sizing: border-box; padding: 0px 5px;">242</li><li style="box-sizing: border-box; padding: 0px 5px;">243</li><li style="box-sizing: border-box; padding: 0px 5px;">244</li><li style="box-sizing: border-box; padding: 0px 5px;">245</li><li style="box-sizing: border-box; padding: 0px 5px;">246</li><li style="box-sizing: border-box; padding: 0px 5px;">247</li><li style="box-sizing: border-box; padding: 0px 5px;">248</li><li style="box-sizing: border-box; padding: 0px 5px;">249</li><li style="box-sizing: border-box; padding: 0px 5px;">250</li><li style="box-sizing: border-box; padding: 0px 5px;">251</li><li style="box-sizing: border-box; padding: 0px 5px;">252</li><li style="box-sizing: border-box; padding: 0px 5px;">253</li><li style="box-sizing: border-box; padding: 0px 5px;">254</li><li style="box-sizing: border-box; padding: 0px 5px;">255</li><li style="box-sizing: border-box; padding: 0px 5px;">256</li><li style="box-sizing: border-box; padding: 0px 5px;">257</li><li style="box-sizing: border-box; padding: 0px 5px;">258</li><li style="box-sizing: border-box; padding: 0px 5px;">259</li><li style="box-sizing: border-box; padding: 0px 5px;">260</li></ul>

服务器2:将信息原样返回去

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>;

<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <cstdio></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <WINSOCK2.H></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <windows.h></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <stdio.h></span>

<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma comment(lib, "Ws2_32.lib")      <span class="hljs-comment" style="box-sizing: border-box;">// Socket编程需用的动态链接库</span></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#pragma comment(lib, "Kernel32.lib")    <span class="hljs-comment" style="box-sizing: border-box;">// IOCP需要用到的动态链接库</span></span>

<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#define PORT 5150</span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#define DATA_BUFSIZE 8192</span>

DWORD WINAPI ServerWorkerThread(LPVOID ComlpetionPortID);


<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span>
{
    OVERLAPPED OVerlapped;
    WSABUF DATABuf;
    CHAR Buffer[DATA_BUFSIZE];
    DWORD BytesSend, BytesRecv;
}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;


<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span>
{
    SOCKET Socket;
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;


DWORD WINAPI ServerWorkerThread(LPVOID ComlpetionPortID);


<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>* argv[])
{
    SOCKADDR_IN InternetAddr;
    SOCKET  Listen, Accept;
    HANDLE  CompetionPort;
    SYSTEM_INFO SystenInfo;
    LPPER_HANDLE_DATA   PerHandleData;
    LPPER_IO_OPERATION_DATA PerIOData;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i;
    DWORD   RecvBytes;
    DWORD   Flags;
    DWORD   ThreadID;
    WSADATA     wsadata;
    DWORD   Ret;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (Ret = WSAStartup(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0x2020</span>, &wsadata) != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)
    {
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"WSAStartup failed with error %d/n"</span>, Ret);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//打开一个空的完成端口</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((CompetionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)) == NULL)
    {
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CreateIoCompletionPort failed with error %d/n"</span>, GetLastError());
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    }

    GetSystemInfo(&SystenInfo);
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 开启cpu个数的2倍个的线程</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < SystenInfo.dwNumberOfProcessors * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>; i++)
    {
        HANDLE  ThreadHandle;

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//创建服务器工作线程,并且向线程传送完成端口</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((ThreadHandle = CreateThread(NULL, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, ServerWorkerThread, CompetionPort, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, &ThreadID)) == NULL)
        {
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CreateThread failed with error %d/n"</span>, GetLastError());
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
        }
        CloseHandle(ThreadHandle);
    }


    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//打开一个服务器socket</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((Listen = WSASocket(AF_INET, SOCK_STREAM, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, NULL, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
    {
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"WSASocket()failed with error %d/n"</span>, WSAGetLastError());
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    }
    InternetAddr.sin_family = AF_INET;
    InternetAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    InternetAddr.sin_port = htons(PORT);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (bind(Listen, (LPSOCKADDR)&InternetAddr, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(InternetAddr)) == SOCKET_ERROR)
    {
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"bind failed with error %d/n"</span>, WSAGetLastError());
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (listen(Listen, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>) == SOCKET_ERROR)
    {
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"listen failed with error %d/n"</span>, WSAGetLastError());
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//接收连接并且分发给完成端口</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (TRUE)
    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((Accept = WSAAccept(Listen, NULL, NULL, NULL, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)) == SOCKET_ERROR)
        {
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"WSAAccept failed with error %d/n"</span>, WSAGetLastError());
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//创建与套接字相关的套接字信息结构</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(PER_HANDLE_DATA))) == NULL)
        {
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"GlobalAlloc failed with error %d/n"</span>, GetLastError());
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Associate the accepted socket with the original completion port.</span>
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Socket number %d connected/n"</span>, Accept);

        PerHandleData->Socket = Accept;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//结构中存入接收的套接字</span>
                                       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//与我们的创建的那个完成端口关联起来,将关键项也与指定的一个完成端口关联</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((CreateIoCompletionPort((HANDLE)Accept, CompetionPort, (DWORD)PerHandleData, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)) == NULL)
        {
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"CreateIoCompletionPort failed with error%d/n"</span>, GetLastError());
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建同下面的WSARecv调用相关的IO套接字信息结构体</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((PerIOData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(PER_IO_OPERATION_DATA))) == NULL)
        {
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"GlobalAloc failed with error %d/n"</span>, GetLastError());
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
        }

        ZeroMemory(&(PerIOData->OVerlapped), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(OVERLAPPED));
        PerIOData->BytesRecv = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
        PerIOData->BytesSend = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
        PerIOData->DATABuf.len = DATA_BUFSIZE;
        PerIOData->DATABuf.buf = PerIOData->Buffer;
        Flags = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (WSARecv(Accept, &(PerIOData->DATABuf), <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, &RecvBytes, &Flags, &(PerIOData->OVerlapped), NULL) == SOCKET_ERROR)
        {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (WSAGetLastError() != ERROR_IO_PENDING)
            {
                <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"WSARecv()failed with error %d/n"</span>, WSAGetLastError());
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
            }
        }
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}

<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//工作线程</span>
DWORD WINAPI ServerWorkerThread(LPVOID ComlpetionPortID)
{
    HANDLE  ComplectionPort = (HANDLE)ComlpetionPortID;
    DWORD   BytesTransferred;
    LPOVERLAPPED Overlapped;
    LPPER_HANDLE_DATA   PerHandleData;
    LPPER_IO_OPERATION_DATA PerIOData;
    DWORD   SendBytes, RecvBytes;

    DWORD   Flags;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (TRUE)
    {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (GetQueuedCompletionStatus(ComplectionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED*)&PerIOData, INFINITE) == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)
        {
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"GetQueuedCompletionStatus failed with error%d/n"</span>, GetLastError());
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//首先检查套接字上是否发生错误,如果发生了则关闭套接字并且清除同套节字相关的SOCKET_INFORATION 结构体</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (BytesTransferred == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)
        {
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Closing Socket %d/n"</span>, PerHandleData->Socket);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
            {
                <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"closesocket failed with error %d/n"</span>, WSAGetLastError());
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
            }
            GlobalFree(PerHandleData);
            GlobalFree(PerIOData);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">continue</span>;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//检查BytesRecv域是否等于0,如果是,说明WSARecv调用刚刚完成,可以用从己完成的WSARecv调用返回的BytesTransferred值更新BytesRecv域</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (PerIOData->BytesRecv == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)
        {
            PerIOData->BytesRecv = BytesTransferred;
            PerIOData->BytesSend = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>
        {
            PerIOData->BytesRecv += BytesTransferred;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (PerIOData->BytesRecv > PerIOData->BytesSend)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//收到数据比发送的多了,就回发出去</span>
        {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//发布另一个WSASend()请求,因为WSASendi 不能确保发送了请的所有字节,继续WSASend调用直至发送完所有收到的字节</span>
            ZeroMemory(&(PerIOData->OVerlapped), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(OVERLAPPED));
            PerIOData->DATABuf.buf = PerIOData->Buffer + PerIOData->BytesSend;
            PerIOData->DATABuf.len = PerIOData->BytesRecv - PerIOData->BytesSend;

            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (WSASend(PerHandleData->Socket, &(PerIOData->DATABuf), <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, &SendBytes, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, &(PerIOData->OVerlapped), NULL) == SOCKET_ERROR)
            {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (WSAGetLastError() != ERROR_IO_PENDING)
                {
                    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"WSASend()fialed with error %d/n"</span>, WSAGetLastError());
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
                }
            }
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>
        {
            PerIOData->BytesRecv = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Now that is no more bytes to send post another WSARecv()request</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//现在己经发送完成</span>
            Flags = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
            ZeroMemory(&(PerIOData->OVerlapped), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(OVERLAPPED));
            PerIOData->DATABuf.buf = PerIOData->Buffer;
            PerIOData->DATABuf.len = DATA_BUFSIZE;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (WSARecv(PerHandleData->Socket, &(PerIOData->DATABuf), <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, &RecvBytes, &Flags, &(PerIOData->OVerlapped), NULL) == SOCKET_ERROR)
            {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (WSAGetLastError() != ERROR_IO_PENDING)
                {
                    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"WSARecv()failed with error %d/n"</span>, WSAGetLastError());
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
                }
            }
        }
    }
}</code>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用IOCP实现的简单服务端程序的示例代码: ``` #include <WinSock2.h> #include <Windows.h> #include <iostream> #pragma comment(lib, "ws2_32.lib") #define BUFFER_SIZE 1024 #define MAX_CLIENTS 10 struct ClientContext { SOCKET socket; char buffer[BUFFER_SIZE]; int bytesReceived; OVERLAPPED overlapped; }; int main() { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); // 创建监听socket SOCKET listenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); SOCKADDR_IN serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); serverAddr.sin_port = htons(12345); bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)); listen(listenSocket, SOMAXCONN); // 创建IOCP HANDLE iocpHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); // 将监听socket加入IOCP CreateIoCompletionPort((HANDLE)listenSocket, iocpHandle, (ULONG_PTR)listenSocket, 0); // 创建客户端上下文数组 ClientContext clientContexts[MAX_CLIENTS]; for (int i = 0; i < MAX_CLIENTS; i++) { clientContexts[i].socket = INVALID_SOCKET; clientContexts[i].bytesReceived = 0; ZeroMemory(&clientContexts[i].overlapped, sizeof(OVERLAPPED)); } // 不断等待客户端连接 while (true) { // 接收客户端连接请求 SOCKET clientSocket = accept(listenSocket, NULL, NULL); // 将客户端socket加入IOCP CreateIoCompletionPort((HANDLE)clientSocket, iocpHandle, (ULONG_PTR)clientSocket, 0); // 找到一个空闲的客户端上下文 ClientContext* clientContext = NULL; for (int i = 0; i < MAX_CLIENTS; i++) { if (clientContexts[i].socket == INVALID_SOCKET) { clientContext = &clientContexts[i]; break; } } if (clientContext == NULL) { std::cout << "Too many clients." << std::endl; closesocket(clientSocket); continue; } // 初始化客户端上下文 clientContext->socket = clientSocket; clientContext->bytesReceived = 0; ZeroMemory(&clientContext->overlapped, sizeof(OVERLAPPED)); // 异步接收数据 DWORD flags = 0; WSARecv(clientSocket, &clientContext->buffer[clientContext->bytesReceived], BUFFER_SIZE - clientContext->bytesReceived, NULL, &flags, &clientContext->overlapped, NULL); } // 关闭监听socket closesocket(listenSocket); // 关闭IOCP CloseHandle(iocpHandle); WSACleanup(); return 0; } ``` 该程序使用IOCP监听客户端连接请求,并异步接收客户端发送的数据。程序中使用了一个客户端上下文数组来保存每个客户端的状态信息。在接收到客户端连接请求时,程序会找到一个空闲的客户端上下文,并将连接的客户端socket加入IOCP。在异步接收数据时,程序使用客户端上下文中的缓冲区来保存已接收到的数据,并在数据接收完成后再次调用WSARecv函数来继续接收数据。程序中使用了OVERLAPPED结构体来实现异步操作。程序使用了WSARecv函数来异步接收数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值