Linux Network programming socket (11) Socket I/O Timeout setting method and timeout with select implementation

Source: Internet
Author: User
Tags socket

Use the alarm function to set a timeout

void handler (int sig)
{
}
signal (SIGALRM, handler);
    
Alarm (5);
int ret = read (FD, buf, sizeof (BUF));
if (ret = = 1 && errno = = eintr)
    errno = etimeout;
else if (ret >= 0)
    alarm (0);
.................

Program general framework as shown above, if read in the 5s by the SIGALRM signal interruption and return, it indicates a timeout, otherwise no timeout has been read to the data, cancel the alarm clock. However, this method is not commonly used because alarm can sometimes cause confusion in other places.

Second, the use of socket options So_sndtimeo, So_rcvtimeo

setsockopt (sock, Sol_socket, So_rcvtimeo, 5);
    
int ret = read (sock, buf, sizeof (BUF));
if (ret = = 1 && errno = = ewouldblock)
    errno = etimeout;
..........

Even if you set it with the SetSockOpt function, this method is less portable, not every system implementation has these options.

Third, the use of select implementation Timeout

The following program contains Read_timeout, Write_timeout, accept_timeout, connect_timeout four function encapsulation

/************************************************************************* > File name:sysutil.c > Author: Simba > Mail:dameng34@163.com > Created time:sat Mar 2013 10:53:06 PM CST ***************************
 /#include "sysutil.h"/* read_timeout-read timeout detection function, excluding read operation * FD: File descriptor * Wait_seconds: Wait timeout number of seconds, if 0 means not detect timeout; * Successful (not timed out) returns 0, failure returns-1, timeout return-1 and errno = etimedout/int read_timeout (int fd, Unsi
    gned int wait_seconds) {int ret = 0;
        if (Wait_seconds > 0) {fd_set read_fdset;
    
        struct Timeval timeout;
        Fd_zero (&read_fdset);
    
        Fd_set (FD, &read_fdset);
        Timeout.tv_sec = Wait_seconds;
    
        timeout.tv_usec = 0;
            do {ret = select (FD + 1, &read_fdset, NULL, NULL, &timeout);//select will block until an event is detected or timed out If the select detects that a readable event is sent, then call read does not block} while (Ret < 0 && ERRno = = eintr);
            if (ret = 0) {ret =-1;
        errno = Etimedout;
    
    else if (ret = 1) return 0;
return ret; }/* Write_timeout-write timeout detection function, does not contain write operation * FD: File descriptor * Wait_seconds: Wait timeout number of seconds, if 0 means not detect timeout; * Successful (not timed out) return 0, Failure return-1, timeout return-1 and Errn
    o = etimedout */int write_timeout (int fd, unsigned int wait_seconds) {int ret = 0;
        if (Wait_seconds > 0) {fd_set write_fdset;
    
        struct Timeval timeout;
        Fd_zero (&write_fdset);
    
        Fd_set (FD, &write_fdset);
        Timeout.tv_sec = Wait_seconds;
    
        timeout.tv_usec = 0;
        do {ret = select (FD + 1, NULL, &write_fdset, NULL, &timeout);
    
        while (Ret < 0 && errno = = eintr);
            if (ret = 0) {ret =-1;
        errno = Etimedout;
    
    else if (ret = 1) return 0;
    
   } return ret; }/* Accept_timeout-Accept * FD with timeout: socket * Addr: Output parameter, return address * wait_seconds: Wait timeout seconds, if 0 indicates normal mode * Successful (not timed out) return connected socket Word, Failure returns-1, timeout return-1 and errno = etimedout/int accept_timeout (int fd, struct sockaddr_in *addr, unsigned int wait_seconds
    ) {int ret;
    
    socklen_t addrlen = sizeof (struct sockaddr_in);
        if (Wait_seconds > 0) {fd_set accept_fdset;
        struct Timeval timeout;
        Fd_zero (&accept_fdset);
    
        Fd_set (FD, &accept_fdset);
        Timeout.tv_sec = Wait_seconds;
    
        timeout.tv_usec = 0;
        do {ret = select (FD + 1, &accept_fdset, NULL, NULL, &timeout);
    
        while (Ret < 0 && errno = = eintr);
        if (ret = = 1) return-1;
            else if (ret = 0) {errno = Etimedout;
        return-1;
 } if (addr!= NULL) ret = Accept (FD, (struct sockaddr *) addr, &addrlen);   else ret = accept (FD, NULL, NULL);
    
    if (ret = = 1) err_exit ("Accpet error");
return ret;
    }/* Activate_nonblock-set IO to non-blocking mode * FD: File descriptor */void Activate_nonblock (int fd) {int ret;
    int flags = FCNTL (FD, F_GETFL);
    
    if (flags = = 1) err_exit ("Fcntl error");
    Flags |= O_nonblock;
    ret = Fcntl (FD, F_SETFL, flags);
if (ret = = 1) err_exit ("Fcntl error");
    }/* Deactivate_nonblock-set IO to blocking mode * FD: File descriptor/void Deactivate_nonblock (int fd) {int ret;
    int flags = FCNTL (FD, F_GETFL);
    
    if (flags = = 1) err_exit ("Fcntl error");
    Flags &= ~o_nonblock;
    ret = Fcntl (FD, F_SETFL, flags);
if (ret = = 1) err_exit ("Fcntl error"); }/* Connect_timeout-with timeout of Connect * FD: Socket * Addr: Output parameter, return address * wait_seconds: Wait timeout seconds, if 0 for normal mode * Successful (not timed out) return 0, lost
    Defeat returns-1, timeout returns-1 and errno = etimedout/int connect_timeout (int fd, struct sockaddr_in *addr, unsigned int wait_seconds) { INT RET;
    
    socklen_t addrlen = sizeof (struct sockaddr_in);
    
    if (Wait_seconds > 0) activate_nonblock (FD);
    ret = connect (FD, (struct sockaddr *) addr, addrlen);
        if (Ret < 0 && errno = einprogress) {fd_set connect_fdset;
        struct Timeval timeout;
        Fd_zero (&connect_fdset);
    
        Fd_set (FD, &connect_fdset);
        Timeout.tv_sec = Wait_seconds;
    
        timeout.tv_usec = 0; Do {/* Once the connection is established, the socket can be written * * ret = SELECT (FD + 1, NULL, &connect_fdset, NULL, &timeout
        );
    
        while (Ret < 0 && errno = = eintr);
            if (ret = = 0) {errno = Etimedout;
        return-1;
    
        else if (Ret < 0) return-1; else if (ret = = 1) {/* RET returns 1, there may be two cases where the connection is successful and one is the socket generates an error * The error message is not saved to the errno variable (select
   No error), therefore, you need to call * getsockopt to get the * *         int err;
            socklen_t Socklen = sizeof (ERR);
            int sockoptret = getsockopt (FD, Sol_socket, So_error, &err, &socklen);
            if (Sockoptret = = 1) return-1;
            if (err = = 0) ret = 0;
                else {errno = err;
            ret =-1;
    
    
    }} if (Wait_seconds > 0) deactivate_nonblock (FD);
return ret; }

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.