简体   繁体   中英

Setting socket timeout for receive function

I have a client server connection where the client is sending data to the server.

while (1) {

    bzero(buffer, 256);
    sleep(1);

    n = read(sock, buffer);
    if(n < 0) error("ERROR reading from socket");
    c = message[0];

    //do something

}//close while loop

The issue i only want to wait for a read to happen only for some seconds - in my code, if the client does not send anything, it gets stuck waiting for the server to read something.

How can I wait for a read to happen only some seconds please?

You can use select() api for this purpose. In this api u can mention the time in select api in seconds and microseconds.

Basically the read call attempts to read so if you don't want to get stack on it you've to declare the sock variable as non-blocking or to use the select function with timeout ( man select ). In the first case you can't wait for some seconds but you can try to read k times and then go through. Here's the example for non-blocking socket:

/*
 * Non-blocking socket solution
 * just put the read in a for-loop
 * if you want to read k times
 */


#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

int r1;
/*Setting the socket as non-blocking*/
int flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags | O_NONBLOCK);
errno = 0; /*If the read fails it sets errno*/
if((r1=read(sock,buf_in,N))== -1) { /*If the read returns an error*/
    if(errno != EAGAIN && errno != EWOULDBLOCK){ /*If the error is not caused by the non-blocking socket*/
                perror("Error in read\n");
                exit(EXIT_FAILURE);
            }
}

Here's the select solution:

/*
 * Select solution.
 * This is not a complete solution but
 * it's almost everything you've to do
 */


#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>

#define SVC(r,c,e)  \
    errno = 0;  \
    if((r=c)==-1) { perror(e);exit(errno); }

int r = 0;
int fd_skt;
fd_set rdset;
fd_set set;
struct timeval tv; /*Timer structure*/
int fd_num_max = 0; /*Maximum opened file descriptor*/
if(fd_skt > fd_num_max) fd_num_max = fd_skt;
FD_ZERO(set);
FD_SET(fd_skt,set); /*fd_skt is where you're waiting for new connection request*/
/*Setting the timer*/
tv.tv_sec = 0;
tv.tv_usec = 200*1000;
rdset = set;
SVC(r,select((fd_num_max+1),(&rdset),NULL,NULL,&tv),"Unable to select\n");

If your socket is non-blocking you can use the select function. If your socket is blocking you can set a read timeout using the setsockopt function. See this stackoverflow question for more details. Linux: is there a read or recv from socket with timeout?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM