Winsock& IOCP:UDP服务器。异步客户端管理

时间:2017-02-07 18:06:33

标签: c++ asynchronous server winsock2 iocp

我有一个winsock-server,接受来自本地IP的数据包,目前无需使用IOCP即可运行。我希望它通过IOCP进行非阻塞。是的我知道替代方案(选择,WSAAsync等),但这不会用于开发MMO服务器。

所以这就是问题 - 如何使用std :: thread和IOCP?

我已经知道GetQueuedCompletionStatus()使数据包出列,而PostQueuedCompletionStatus()将这些数据包排队到IOCP。 这是实现异步的正确方法吗?

如何在大约10个线程上平等地威胁所有客户?我考虑过接收UDP数据包并处理这些数据包,而IOCP在队列中有一些东西,但数据包将一次处理10个数据包,并且每个线程中也有一个无限循环。

目标是创建一个游戏服务器,能够同时容纳数千个客户端。

关于代码:netListener()是一个类,用于保存从向量中的侦听网络接口接收的数据包。它在Receive()中所做的只是

WSARecvFrom(sockfd, &buffer, 1, &bytesRecv, &flags, (SOCKADDR*)&senderAddr, &size, &overl, 0); std::cout << "\n\nReceived " << bytesRecv << " bytes.\n" << "Packet [" << std::string(buffer.buf, bytesRecv)<< "]\n"; *

代码有效,缓冲区显示我发送给自己的内容,但我不确定是否只有一个receive()就足够了。

关于阻塞 - 是的,我意识到将listener.Receive()放入一个单独的线程不会阻塞主线程。但想象一下 - 许多客户端尝试发送数据包,是否可以接收所有数据包?更不用说我计划在每次接收时排队IOCP数据包,但仍不确定如何正确地执行此操作。

另一个问题 - 是否可以在客户端和另一个客户端之间建立直接连接?如果您在NAT后面的本地计算机上托管服务器,并且您希望可以从Internet访问它,例如。

主题:

void Host::threadFunc(int i) {
threadMutex.lock();
for (;;) {
    if (m_Init) {
        if (GetQueuedCompletionStatus(iocp, &bytesReceived, &completionKey, (LPOVERLAPPED*)&overl, WSA_INFINITE)) {
            std::cout << "1 completion packet dequeued, bytes: " << bytesReceived << std::endl;
        }
    }
}

threadMutex.unlock(); }


void Host::createThreads() {
//Create threads
for (unsigned int i = 0; i < SystemInfo.dwNumberOfProcessors; ++i) {
    threads.push_back(std::thread(&Host::threadFunc, this, i));
    if (threads[i].joinable()) threads[i].detach();
}
std::cout << "Threads created: " << threads.size() << std::endl; }

主机

Host::Host() {
using namespace std;
InitWSA();

createThreads();
m_Init = true;
SecureZeroMemory((PVOID)&overl, sizeof(WSAOVERLAPPED));
overl.hEvent = WSACreateEvent();
iocp = CreateIoCompletionPort((HANDLE)sockfd, iocp, 0, threads.size());

listener = netListener(sockfd, overl, 12); //12 bytes buffer size
for (int i = 0; i < 4; ++i) { //IOCP queue test
    if (PostQueuedCompletionStatus(iocp, 150, completionKey, &overl)) {
        std::cout << "1 completion packet queued\n";
    }
}
std::cin.get();
listener.Receive(); //Packet receive test - adds a completion packet n bytes long if client sent one
std::cin.get();}

0 个答案:

没有答案