UDP recvfrom线程占用过多CPU资源

问题描述 投票:2回答:4

我正在编写一个Windows 7 visual c++服务器应用程序,它应该接收3.6 MBs的UDP数据报,我有一个主线程,其中recvfrom()接收数据。我有一个主线程,recvfrom()在其中接收数据,该套接字是一个非阻塞套接字,有64kB的接收缓冲区。如果在socket上没有收到数据,线程就会执行sleep(1)。

我的问题是,这个线程几乎占用了我的双核处理器的50%,我不知道如何减少它。Wireshark只用了20%,所以我的主要目标是达到类似的比例。

你有什么好办法吗?

c++ multithreading sockets udp winsockets
4个回答
4
投票

与轮询相比,你可以使用类似select的方法来等待数据到达你的套接字或者客户端决定关闭。

首先使你的套接字是非阻塞的

u_long nonBlocking = 0;
WSAEventSelect(sock, NULL, 0);
ioctlsocket(sock, FIONBIO, &nonBlocking);

然后使用 WSAWaitForMultipleEvents 以等待数据到达或你想取消recv。

int32_t MyRecv(THandle sock, WSAEVENT* recvCancelEvt,
               uint8_t* buffer, uint32_t bufferBytes)
{
    int32_t bytesReceived;
    WSAEVENT evt;
    DWORD ret;
    HANDLE handles[2];

    event = WSACreateEvent();
    if (NULL == evt) {
        return;
    }
    if (0 != WSAEventSelect(handle->iSocket, evt, FD_READ|FD_CLOSE)) {
        WSACloseEvent(event);
        return;
    }

    bytesReceived = recv(sock, (char*)buffer, bufferBytes, 0);
    if (SOCKET_ERROR==received && WSAEWOULDBLOCK==WSAGetLastError()) {
        handles[0] = evt;
        handles[1] = *recvCancelEvt;
        ret = WSAWaitForMultipleEvents(2, handles, FALSE, INFINITE, FALSE);
        if (WAIT_OBJECT_0 == ret) {
            bytesReceived = recv(handle->iSocket, (char*)buffer, bufferBytes, 0);
        }
    }
    WSACloseEvent(evt);
    return bytesReceived;
}

客户端代码会调用 WSASetEvent 关于 recvCancelEvt 如果它想取消一个recv。


1
投票

虽然基于Select或阻塞套接字的解决方案是正确的方法,但你的一个核心100%运行的原因是由于Sleep:-的行为。

请看文档中的 WinAPI sleep():

该函数使线程放弃其时间片的剩余部分,并根据dwMilliseconds的值在一段时间内无法运行。系统时钟以恒定的速度 "滴答"。如果dwMilliseconds小于系统时钟的分辨率,线程的睡眠时间可能小于指定的时间长度。

所以,如果你在进行轮询,你要么需要使用更大的睡眠时间(可能是20Ms,通常比Windows的tick率大一些),要么使用更精确的多媒体定时器。


0
投票

我建议使用 boost::asio::io_service。我们收到大约200MBs的UDP多播流量,同时最大限度地使用现代CPU。这包括一个完整的可靠性协议和对应用程序的数据调度。剖析的瓶颈是处理,而不是boost::asio receive。代码在这里


0
投票

看来你的recvfrom的调用大部分时候都没有返回数据。睡眠1毫秒的时间并不多。你应该考虑增加睡眠时间(便宜,但不是最好的解决方案),或者,更好的解决方案是考虑使用事件驱动的方法。使用 "事件驱动 "的方法。select() 或Windows API来阻止,直到套接字发出信号或其他你感兴趣的事件发生,然后调用 recvfrom. 你可能需要重新设计你的程序的主循环。

© www.soinside.com 2019 - 2024. All rights reserved.