Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add delay to sento and recvfrom in UDP client/server in C

Tags:

c

sockets

For a programming project in school we have to design a basic client/server setup using tcp protocol and then udp protocol. I already got the TCP working using read() and write() from the C Socket library. I now need to create a "reliable UDP" system. For instance:

"When the server receives the length message it will wait up to 500 milliseconds for that number of bytes to be sent. If it receives the correct number of bytes, it will respond with a string containing the characters "ACK" (a common abbreviation for an acknowledgement). If it does not receive the correct number of bytes by the end of the timeout period, the server will give up and silently exit."

I have the sendto() and recvfrom() functions set up, but I am not sure how to do the timeout feature so that it only waits 500ms for the second msg to be sent. I also have to do it later on the client side if it doesn't receive the "ACK" and resend the length msg + msg a few times. How can do I do the timeout?

like image 873
MasterGberry Avatar asked Jan 15 '23 10:01

MasterGberry


2 Answers

Add the following function in your program and use it instead of using the recvfrom function directly.

the following functiong has the same input parameter of recvfrom function + a timeout input parameter in the last

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

int timeout_recvfrom (int sock, char *buf, int *length, struct sockaddr_in *connection, int timeoutinseconds)
{
    fd_set socks;
    struct timeval t;
    FD_ZERO(&socks);
    FD_SET(sock, &socks);
    t.tv_sec = timeoutinseconds;
    if (select(sock + 1, &socks, NULL, NULL, &t) &&
        recvfrom(sock, buf, *length, 0, (struct sockaddr *)connection, length)!=-1)
        {
        return 1;
        }
    else
        return 0;
}
like image 70
MOHAMED Avatar answered Jan 29 '23 23:01

MOHAMED


An alternate without using select or poll is using socket options SO_RCVTIMEO and SO_SNDTIMEO

tv.tv_sec = 10; /* seconds */
tv.tv_usec = 0;

if(setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
        printf("Cannot Set SO_SNDTIMEO for socket\n");

if(setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
        printf("Cannot Set SO_RCVTIMEO for socket\n");

SO_RCVTIMEO and SO_SNDTIMEO socket options

If you have a single socket to either read or write to/from, then this is a better option. Where as if you are using multiple sockets and wish to carry on with the one which completely sent / received data, then perhaps select would be more appropriate.

like image 32
fkl Avatar answered Jan 30 '23 01:01

fkl