Bootstrap

window下IOPC

 服务器:

#pragma once
//https://www.cnblogs.com/xiaobingqianrui/p/9258665.html
//完成端口(IOCP)编程
#include <iostream>
#include <thread>

//网络编程三个文件
#include<WS2tcpip.h>
#include <winsock2.h>
#include <windows.h>
#include <minwindef.h>
#include <vector>


#pragma comment(lib,"ws2_32.lib")
 
using namespace std;
HANDLE g_hIOCP;//完成端口描述符

enum class IO_OPERATION : int
{
	IO_READ,
	IO_WRITE
};

struct IO_DATA{
    OVERLAPPED                  Overlapped;
    WSABUF                      wsabuf;
    int                         nBytes;
    IO_OPERATION                opCode;
    SOCKET                      client;
};
 
char buffer[1024];//缓冲区,接受发送的数据都存在这里
 
inline DWORD  WorkerThread()
{
    IO_DATA *lpIOContext = nullptr; 
    DWORD nBytes = 0;
    DWORD dwFlags = 0; 
    int nRet = 0;

    DWORD dwIoSize = 0; 
    void * lpCompletionKey = nullptr;
    LPOVERLAPPED lpOverlapped = nullptr;

    while(true){
        //缓冲区有数据时就会继续执行,没数据就会阻塞
        GetQueuedCompletionStatus(g_hIOCP, &dwIoSize,reinterpret_cast<LPDWORD>(&lpCompletionKey),static_cast<LPOVERLAPPED *>(&lpOverlapped), INFINITE);
        lpIOContext = reinterpret_cast<IO_DATA *>(lpOverlapped);
        cout<<"["<<this_thread::get_id()<<"]线程"<<", Size:"<<sizeof(lpIOContext) << ", 地址:"<< lpIOContext<<endl;
        if(dwIoSize == 0)
        {
            cout << "Client disconnect" << endl;
            closesocket(lpIOContext->client);
            delete lpIOContext;
            continue;
        }
        if(lpIOContext->opCode == IO_OPERATION::IO_READ) // a read operation complete
        {
            cout<<"["<<this_thread::get_id()<<"]线程"<<"收到客户端的消息:"<< lpIOContext->wsabuf.buf<<endl;
            ZeroMemory(&lpIOContext->Overlapped, sizeof(lpIOContext->Overlapped));
            lpIOContext->wsabuf.buf = buffer;
            lpIOContext->wsabuf.len = strlen(buffer)+1;
            lpIOContext->opCode = IO_OPERATION::IO_WRITE;
            lpIOContext->nBytes = strlen(buffer)+1;
            dwFlags = 0;//必须为0
            string sendMsg = "send 线程";//要发给客户端的消息
            strcpy_s(buffer, sendMsg.c_str());
            nBytes = strlen(buffer)+1;
            nRet = WSASend(
                lpIOContext->client,
                &lpIOContext->wsabuf, 1, &nBytes,
                dwFlags,
                &(lpIOContext->Overlapped), nullptr);
            if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {
                cout << "WASSend Failed::Reason Code::"<< WSAGetLastError() << endl;
                closesocket(lpIOContext->client);
                delete lpIOContext;
                continue;
            }
            cout<<"["<<this_thread::get_id()<<"]线程"<<"发给客户端的消息:"<< lpIOContext->wsabuf.buf<<endl;
            memset(buffer, 0, sizeof(buffer));//重置
        }
        else if(lpIOContext->opCode == IO_OPERATION::IO_WRITE) //a write operation complete
        {
            // Write operation completed, so post Read operation.
            lpIOContext->opCode = IO_OPERATION::IO_READ; 
            nBytes = 1024;
            dwFlags = 0;
            lpIOContext->wsabuf.buf = buffer;
            lpIOContext->wsabuf.len = nBytes;
            lpIOContext->nBytes = nBytes;
            ZeroMemory(&lpIOContext->Overlapped, sizeof(lpIOContext->Overlapped));
            nRet = WSARecv(
                lpIOContext->client,
                &lpIOContext->wsabuf, 1, &nBytes,
                &dwFlags,
                &lpIOContext->Overlapped, nullptr);
            if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {
                cout << "WASRecv Failed::Reason Code1::"<< WSAGetLastError() << endl;
                closesocket(lpIOContext->client);
                delete lpIOContext;//就是父线程的data
                continue;
            } 
        }
    }
    return 0;
}
inline void start()
{
    WSADATA wsaData;
    WORD sockVersion = MAKEWORD(2, 0);
	if (0 != WSAStartup(sockVersion, &wsaData))
	{
		cout << "Failed to retrive socket version."<< endl;
		return;
	}
    SOCKET socketServer = WSASocket(AF_INET,SOCK_STREAM, IPPROTO_TCP, nullptr,0,WSA_FLAG_OVERLAPPED);
    sockaddr_in server{};
    server.sin_family = AF_INET;
    server.sin_port = htons(8000);
    server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    bind(socketServer ,reinterpret_cast<sockaddr*>(&server),sizeof(server));
    listen(socketServer, 8);

    //IOCP
    SYSTEM_INFO sysInfo; 
    GetSystemInfo(&sysInfo);//获取当前系统的信息。在cmd中Systeminfo命令可获取
    auto g_ThreadCount = sysInfo.dwNumberOfProcessors * 2;
    g_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE,nullptr, 0, g_ThreadCount);

    //创建一堆线程用来读写
    for( decltype(g_ThreadCount) i = 0;i < g_ThreadCount; ++i){
        std::thread t(&WorkerThread);
        t.detach(); 
    }
    //读写操作
    while(true)
    {
        sockaddr_in revClientAddr{};		
	    int _revSize = sizeof(sockaddr_in);

        //阻塞在这里等客户端请求连接
        SOCKET socketClient = accept(socketServer, reinterpret_cast<SOCKADDR*>(&revClientAddr), &_revSize);
        if (SOCKET_ERROR != socketClient){cout << "客户端连接成功" << endl;}
        //将新连接的客户端关联到IOCP
        if (CreateIoCompletionPort(reinterpret_cast<HANDLE>(socketClient), g_hIOCP, 0, 0)== nullptr)
        {
	        cout << "Binding Client Socket to IOCP Failed::Reason Code::"<< GetLastError() << endl;
            closesocket(socketClient);
        }
        else
        {
            auto data(new IO_DATA);
            memset(buffer, 0 ,1024);
            memset(&data->Overlapped, 0 , sizeof(data->Overlapped));
            data->opCode = IO_OPERATION::IO_READ;
            data->nBytes = 0;
            data->wsabuf.buf  = buffer;
            data->wsabuf.len  = sizeof(buffer);
            data->client = socketClient;
            DWORD nBytes= 1024 ,dwFlags=0;
            //客户端连接成功后,需要调用WSARecv将数据发到缓冲区,才能启动工作线程,也就是GetQueuedCompletionStatus执行
            //调用WSARecv之后,buffer中不一定有数据
        	int nRet = WSARecv(data->client, &data->wsabuf, 1, &nBytes, &dwFlags, &data->Overlapped, nullptr);
        	if(nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError())){
               cout << "WASRecv Failed::Reason Code::"<< WSAGetLastError() << endl;
               closesocket(data->client);
               delete data;
            }
            cout<<"Size:"<<sizeof(data) << ", 地址:"<< data<<endl;
        } 
    }
    closesocket(socketServer);
    WSACleanup();
}
 

客户端:

进程间通信之socket_yang_aq的博客-CSDN博客

;