2

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

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.

My Code for Polling:

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;
        }
     }
}

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.

Thanks in Advance

Edit

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

1 Answers1

3

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.

Try this instead:

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;
}

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));
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • why 0 in Select function? – Chandrapal Singh Jhala Aug 24 '18 at 04:02
  • @ChandrapalSinghJhala something in the original question made me think originally that the code was targeting Winsock, which ignores the 1st parameter of `select()`. But re-reading the question again, I don't see what made me think that, so I have replaced the 0 with `Sock + 1`, which is required on non-Windows platforms. – Remy Lebeau Aug 24 '18 at 05:14
  • @ChandrapalSinghJhala the only way that can happen is if the socket is not receiving any data. And FWIW, 30 **microseconds** is a VERY short timeout to use for a socket. Honestly, at that small a time, I would just get rid of `select()` and let `recvfrom()` block until data arrives. Optionally using `SO_RCVTIMEO` to timeout a blocking read. If you are going to use `select()`, a much larger timeout is generally preferred (on the order of **seconds** instead) and break the loop when no data is being received, so you don't hang your app indefinitely – Remy Lebeau Aug 24 '18 at 15:19
  • Wireshark showing that camera is sending packets. I am using 57181 port. First I think it is because of firewall but I turn off the firewall but still I am getting the timeout even if I replace m_timeInterval.tv_sec = 0 to 1 – Chandrapal Singh Jhala Aug 25 '18 at 06:30
  • @ChandrapalSinghJhala then you are likely not setting up the socket correctly. Please show your actual code that creates the socket before entering the `select` loop. – Remy Lebeau Aug 25 '18 at 07:08