C++ IOCP套接字,不确定下一步要做什么
我学习了如何使用Windows Message Proc创建套接字,并打开FD_CONNECT、FD_ACCEPT、FD_CLOSE等。。我使用了: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
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,我也不知道接下来要做什么。也许明天,等我清醒过来。同时,你能发布“这个->工人”的代码吗?