在 Windows 上使用 C++ 中的 Select 函数进行轮询 [英] Polling using Select function in C++ on Windows

查看:75
本文介绍了在 Windows 上使用 C++ 中的 Select 函数进行轮询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是套接字编程的新手.我正在尝试创建一个使用 Sockets 进行通信的应用程序.

I am new in Socket Programming. I am trying to create a Application that uses Sockets for Communication.

我对 Receive 函数有疑问,因为有时它只是挂在 recvfrom 函数中.我正在使用 select 函数进行轮询.它在连接相机时工作,但如果我移除相机,它不会显示错误消息.

I have doubt in the Receive function because sometime it just hangs in recvfrom function. I am using select function for polling. It works when Camera is connected but If I remove Camera it doesn't show the Error Message.

我的投票代码:

FD_ZERO(&m_readFds);
FD_SET(Sock, &m_readFds);

m_timeInterval.tv_usec = 30;            //30 Microseconds for Polling
m_socketLength = sizeof(m_cameraInfo);

m_lastBlockId = -1;

while (m_acquiringThreadStatus)
{
    FD_CLR(Sock, &m_readFds);
    FD_SET(Sock, &m_readFds);

    m_receivingStatus = select(Sock + 1, &m_readFds, NULL, NULL, &m_timeInterval);
    if (m_receivingStatus < 0)
    {
        std::cout << "No Data to Receive"<<std::endl;
    }
    else
    {
        if ((m_receivedBytes = recvfrom(Sock, m_packetBuffer, RECEIVING_BUFFER_SIZE, 0, (struct sockaddr*)&m_cameraInfo, &m_socketLength)) == SOCKET_ERROR)
        {
            std::cout << "ERROR" << std::endl;
        }
        else
        {
            std::cout<<"Data Received"<<std::endl;
        }
     }
}

还有一个问题是,当我在一段时间后继续打印 Data Received 语句时它会停止.那么如何增加 Socket Receiving Buffer.

An one more question is that when I continously printing the Data Received Statement after sometime It stop. So how can I increase the size of Socket Receiving Buffer.

提前致谢

编辑

SOCKET m_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(m_sock == INVALID_SOCKET)
{
// Error
}
else
{
//In the else part bind the socket 
}

推荐答案

如果您阅读 select() 的文档,您会看到 select() 返回 -错误为 1,超时为 0,请求的事件为 > 0.但是,这不是您处理返回值的方式.您将 -1 视为超时,将 >= 0 视为数据事件.因此,当没有任何内容可供读取时,您最终会调用 recvfrom().如果套接字处于阻塞模式(其默认模式),recvfrom() 将阻塞调用线程,直到数据实际可用.

If you read select()'s documentation, you would see that select() returns -1 on error, 0 on timeout, and > 0 on requested event(s). However, that is not how you are treating the return value. You are treating -1 as timeout and >= 0 as data events. So, you end up calling recvfrom() when there is nothing available to read. If the socket is in blocking mode (its default mode), recvfrom() will block the calling thread until data is actually available.

试试这个:

m_lastBlockId = -1;

while (m_acquiringThreadStatus)
{
    FD_ZERO(&m_readFds);
    FD_SET(Sock, &m_readFds);

    m_timeInterval.tv_sec = 0;
    m_timeInterval.tv_usec = 30; //30 Microseconds for Polling

    m_receivingStatus = select(Sock + 1, &m_readFds, NULL, NULL, &m_timeInterval);

    if (m_receivingStatus == SOCKET_ERROR)
    {
        std::cout << "ERROR" << std::endl;
        break;
    }

    if (m_receivingStatus == 0)
    {
        std::cout << "No Data to Receive" << std::endl;
        continue;
    }

    m_socketLength = sizeof(m_cameraInfo);
    if ((m_receivedBytes = recvfrom(Sock, m_packetBuffer, RECEIVING_BUFFER_SIZE, 0, (struct sockaddr*)&m_cameraInfo, &m_socketLength)) == SOCKET_ERROR)
    {
        std::cout << "ERROR" << std::endl;
        break;
    }

    std::cout << "Data Received" << std::endl;
}

关于socket接收缓冲区的大小,可以通过setsockopt()使用SO_RCVBUF选项来设置,例如:

As for the size of the socket's receive buffer, you can set it via setsockopt() using the SO_RCVBUF option, eg:

int bufsize = ...;
setsockopt(Sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, sizeof(bufsize));

这篇关于在 Windows 上使用 C++ 中的 Select 函数进行轮询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆