Search code examples
c++socketsudpdelaysendto

C++, UDP, sendto needs delay to work


I am programming a UDP Relaying Server in C++. But I have a problem.

I have a basic loop that just calls recvfrom(), checks for errors in the packet, then reads the "target" out of the packet and uses sendto() on the same socket to send a packet to the target client that is also relaying on the same server.

The problem is that nearly all packets get lost if I don't add a delay before the sendto() (this delay depends on the connection speed, so I can´t set it statically).

m_iSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
bind(m_iSocket, (SOCKADDR*)&m_oSockAddress, sizeof(SOCKADDR_IN));
...
while(true) {
    recvfrom(m_iSocket, (char*)m_pRecvBuffer, m_nBufferSize, 0, (SOCKADDR*)&remoteAddr, &remoteAddrLen);
    ...
    sendto(m_iSocket, reinterpret_cast<char*>(rw.getData()), rw.getBufferSize(), 0, targets address , address size);
}

Any ideas?


Solution

  • Any ideas?

    Most likely your outgoing UDP packets are getting dropped because a buffer is overflowing somewhere. The most likely place for it to overflow would be in your socket's own outgoing-data buffer; if so, you might be able to reduce the number of dropped packets by calling setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, ...) to make your socket's outgoing-buffer-size larger (i.e. large enough to send hold all of the packets you pass over via sendto() calls at one time).

    If that's not enough to deal with the problem, then the next thing you can do is implement your own in-application buffering; i.e. instead of just immediately calling sendto(), push the packet data to the tail of a FIFO data structure, and then only call sendto() when the socket select()'s as ready-for-write (and when that happens, pop the next packet from the head of the FIFO and call sendto() with that). That way you're always sending data only at the speed the socket's buffer can accept it, rather than assuming the socket's buffer will always be large enough to immediately accept everything you throw at it.

    (The other place where a buffer might be overflowing is on the receiving app's socket's receive-buffer, in which case a call to setsockopt(s, SOL_SOCKET, SO_RCVBUF, ...) on the receiving app's socket might also help)