Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ IOCP套接字,不确定下一步要做什么_C++_Sockets_Iocp - Fatal编程技术网

C++ IOCP套接字,不确定下一步要做什么

C++ IOCP套接字,不确定下一步要做什么,c++,sockets,iocp,C++,Sockets,Iocp,我学习了如何使用Windows Message Proc创建套接字,并打开FD_CONNECT、FD_ACCEPT、FD_CLOSE等。。我使用了:WSAAsyncSelect(socket、WindowHandle、WM_socket、FD|u READ | FD|u WRITE | FD|u CONNECT | FD|u CLOSE | FD|u ACCEPT) 这让我知道套接字何时被接受、关闭、接收数据,而无需对其进行轮询 现在,我正试图学习对控制台应用程序执行相同的操作,但使用IOCP

我学习了如何使用Windows Message Proc创建套接字,并打开FD_CONNECT、FD_ACCEPT、FD_CLOSE等。。我使用了:
WSAAsyncSelect(socket、WindowHandle、WM_socket、FD|u READ | FD|u WRITE | FD|u CONNECT | FD|u CLOSE | FD|u ACCEPT)

这让我知道套接字何时被接受、关闭、接收数据,而无需对其进行轮询

现在,我正试图学习对控制台应用程序执行相同的操作,但使用IOCP

我写了以下内容:

#include <Winsock2.h>
#include <Ws2tcpip.h>
#include <Windows.h>
#include <iostream>
#include <thread>
#include <stdexcept>
#include <cstring>

class Socket
{
    private:
        typedef struct
        {
            OVERLAPPED Overlapped;
            WSABUF DataBuf;
            char Buffer[1024];
            unsigned int BytesSent;
            unsigned int BytesReceived;
        } PER_IO_OPERATION_DATA;

        typedef struct
        {
            SOCKET Sock;
        } PER_HANDLE_DATA;


    protected:
        void Close();
        std::function<void(HANDLE)> Worker;

    public:
        Socket();
        bool Start(std::string Address, unsigned int Port, bool Listen);

        void Read(char* Buffer, int bufflen); //reads from a socket.
        void Write(char* Buffer, int bufflen); //writes to a socket.
        bool Accept();  //accepts a socket.

        virtual void OnRead();   //Called when Reading.
        virtual void OnWrite();  //Called when Writing.
        virtual void OnAccept(); //Called when a socket has been accepted.
        virtual void OnConnect();  //Called when connected.
        virtual void OnDisconnect(); //Called when disconnected.
};

bool Socket::Start(std::string Address, unsigned int Port, bool Listen)
{
    WSADATA wsaData;
    SOCKET sock = 0;
    struct sockaddr_in* sockaddr_ipv4;

    //WSA Startup and getaddrinfo, etc.. here..

    //Create IOCP Handle and worker threads.
    HANDLE IOCPPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0);
    if (!IOCPPort)
    {
        this->Close();
        throw std::runtime_error("Error: Creating IOCP Failed With Error: " + std::to_string(GetLastError()));
    }

    SYSTEM_INFO SystemInfo = {0};
    GetSystemInfo(&SystemInfo);
    for (std::size_t I = 0; I < SystemInfo.dwNumberOfProcessors * 2; ++I)
    {
        std::thread(this->Worker, IOCPPort).detach();
    }

    //Set the socket to overlapped.
    if ((sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, nullptr, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
    {
        this->Close();
        throw std::runtime_error("Error: ");
    }

    struct sockaddr_in SockAddr;
    std::memset(&SockAddr, 0, sizeof(SockAddr));
    SockAddr.sin_port = htons(Port);
    SockAddr.sin_family = AF_INET;
    SockAddr.sin_addr.s_addr = (Address == "INADDR_ANY" ? htonl(INADDR_ANY) : inet_addr(Address.c_str()));

    //If it is a server socket being created, bind it.
    if (Listen && (bind(sock, reinterpret_cast<SOCKADDR*>(&SockAddr), sizeof(SockAddr)) == SOCKET_ERROR))
    {
        this->Close();
        throw std::runtime_error("Error: ");
    }

    //If it is a server socket, start listenening.
    if (Listen && (listen(sock, SOMAXCONN) == SOCKET_ERROR))
    {
        this->Close();
        throw std::runtime_error("Error: ");
    }

    //Otherwise it is a client socket so just connected..
    //if(!Listen && (connect(this->socket, reinterpret_cast<SOCKADDR*>(&SockAddr), sizeof(SockAddr)) == SOCKET_ERROR))


    //Associate this socket with a completion port.
    if (CreateIoCompletionPort(reinterpret_cast<HANDLE>(sock), IOCPPort, 0, 0) != IOCPPort)
    {
        this->Close();
        throw std::runtime_error("Error: ");
    }

    //setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)sdListen, sizeof(sdListen));
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类套接字
{
私人:
类型定义结构
{
重叠;
WSABUF数据库;
字符缓冲区[1024];
无符号整数字节;
接收到无符号整数字节;
}每操作数据;
类型定义结构
{
插座;
}PER_处理_数据;
受保护的:
无效关闭();
功能工人;
公众:
套接字();
bool启动(std::字符串地址,无符号int端口,bool侦听);
void Read(char*Buffer,int bufflen);//从套接字读取。
void Write(char*Buffer,int bufflen);//写入套接字。
bool Accept();//接受套接字。
虚拟void OnRead();//读取时调用。
虚拟void OnWrite();//写入时调用。
虚拟void OnAccept();//在接受套接字时调用。
虚拟void OnConnect();//连接时调用。
虚拟void OnDisconnect();//在断开连接时调用。
};
bool套接字::Start(std::字符串地址,无符号int端口,bool侦听)
{
WSADATA WSADATA;
插座插座=0;
*sockaddr_ipv4中的结构sockaddr_;
//WSA启动和getaddrinfo等。。
//创建IOCP句柄和工作线程。
HANDLE IOCPort=CreateIoCompletionPort(无效的句柄值,nullptr,0,0);
如果(!IOCPPort)
{
此->关闭();
抛出std::runtime_error(“错误:创建IOCP失败,错误:”+std::to_string(GetLastError());
}
系统信息系统信息={0};
GetSystemInfo(&SystemInfo);
对于(std::size\u t I=0;IWorker,IOCPPort).detach();
}
//将插座设置为重叠。
if((sock=WSASocket(AF_INET,sock_STREAM,IPPROTO_TCP,nullptr,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
{
此->关闭();
抛出std::runtime_错误(“错误:”);
}
sockaddr中的结构sockaddr_;
std::memset(&SockAddr,0,sizeof(SockAddr));
SockAddr.sinu port=htons(端口);
SockAddr.sin_family=AF_INET;
SockAddr.sin\u addr.s\u addr=(Address=“INADDR\u ANY”?htonl(INADDR\u ANY):inet\u addr(Address.c\u str());
//如果它是正在创建的服务器套接字,请绑定它。
if(Listen&(bind(sock,reinterpret_cast(&SockAddr),sizeof(SockAddr))==SOCKET_ERROR))
{
此->关闭();
抛出std::runtime_错误(“错误:”);
}
//如果是服务器套接字,请开始侦听。
if(侦听&&(侦听(sock,SOMAXCONN)=套接字错误))
{
此->关闭();
抛出std::runtime_错误(“错误:”);
}
//否则它是一个客户端套接字,因此刚刚连接。。
//如果(!Listen&&(connect(this->socket,reinterpret_cast(&SockAddr),sizeof(SockAddr))==socket_ERROR))
//将此套接字与完成端口关联。
如果(CreateIoCompletionPort(重新解释强制转换(sock),IOCPort,0,0)!=IOCPort)
{
此->关闭();
抛出std::runtime_错误(“错误:”);
}
//setsockopt(sock,SOL_SOCKET,SO_UPDATE_ACCEPT_CONTEXT,(char*)sdListen,sizeof(sdListen));
}
然而,现在我被卡住了。我不确定创建IoCompletionPort后需要做什么。我如何知道套接字何时被接受以便调用OnAccept,或者如何知道何时有数据要读取以便调用OnRead?我浏览了谷歌上的所有页面,没有找到任何类似于OnRead、OnAccept或OnWrite的内容


我只是想让它具有可伸缩性,并在不使用事件或消息循环的情况下为发生的事情提供回调。我在谷歌上看到的唯一让我感兴趣的是IOCP,但我完全迷路了。你知道我下一步需要做什么吗?

很久以前我写了一些关于IOCP服务器设计的文章,我还有一些代码可以下载,这些代码为你做了基础工作


您可以从中获取代码并找到文章的链接。它们可能会帮助您了解接下来会发生什么,以及如何构造IOCP客户端或服务器。

TBH,我也不知道接下来要做什么。也许明天,等我清醒过来。同时,你能发布“这个->工人”的代码吗?