国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Linux > 正文

服務器編程入門(13) Linux套接字設置超時的三種方法

2024-06-28 13:27:03
字體:
來源:轉載
供稿:網友
服務器編程入門(13) linux套接字設置超時的三種方法

摘要:

    本文介紹在套接字的I/O操作上設置超時的三種方法。


套接字超時

圖片可能有點寬,看不到的童鞋可以點擊圖片查看完整圖片。。


1 調用alarm

使用SIGALRM為connect設置超時

設置方法:

  1. 監聽SIGALRM信號,
  2. 設置sig_alrm處理函數,
  3. 在阻塞函數前調用alarm函數設置超時時間,
  4. 正常返回后,重置超時事件為0
void handle_msg(int sockfd) {    char sendbuf[BUFSIZE];    char recvbuf[BUFSIZE];        signal(SIGALRM, sig_alrm);    //監聽SIGALRM信號     while(1) {        memset( sendbuf, '/0', BUFSIZE );        memset( recvbuf, '/0', BUFSIZE );                PRintf("%s", "send msg:");        gets(sendbuf);        if (strlen(sendbuf) > 0)            send(sockfd,sendbuf,strlen(sendbuf),0);        if ( !strcmp(sendbuf, "exit"))            break;        alarm(5);       //設置超時事件為5s,同時設置服務器回射前sleep 10秒,以讓recv函數超時        if (recv(sockfd,recvbuf,BUFSIZE,0) > 0) {            alarm(0);            printf("recv back:%s/n/n", recvbuf);        }        else {            if (errno == EINTR)                fprintf(stderr,                        "socket timeout/n");            else                fprintf(stderr,                        "receive error/n");        }    }    close( sockfd );    return;}static void sig_alrm(int signo) {    fprintf(stderr,            "recv SIGALRM, return./n");    return;}

運行截圖:

image

雖然設置了SIGALRM信號處理函數,但是如圖所示,本例依然可以等待讀取回射信息,因為信號處理函數里只是return。


2 使用select阻塞等待I/O

設置方法:

使用select的內置時間限制,阻塞在select代替recv函數的阻塞。

void handle_msg(int sockfd) {    char sendbuf[BUFSIZE];    char recvbuf[BUFSIZE];    while(1) {        memset( sendbuf, '/0', BUFSIZE );        memset( recvbuf, '/0', BUFSIZE );                printf("%s", "send msg:");        gets(sendbuf);        if (strlen(sendbuf) > 0)             send(sockfd,sendbuf,strlen(sendbuf),0);        if ( !strcmp(sendbuf, "exit"))            break;                if (readable_timeo(sockfd, 5) == 0) {            fprintf(stderr,                    "socket timeout/n");        }        else{            recv(sockfd,recvbuf,BUFSIZE,0);            printf("recv back:%s/n/n", recvbuf);        }    }    close( sockfd );    return;}int readable_timeo(int fd, int sec) {    fd_set rset;    struct timeval tv;        FD_ZERO(&rset);    FD_SET(fd, &rset);    tv.tv_sec = sec;    tv.tv_usec = 0;    return select(fd+1, &rset, NULL, NULL, &tv);}

 

運行截圖:

image

由運行截圖可以看到,超時警告運行正常。

需要注意一點的是,雖然客戶端在超時之后繼續發送消息,但是服務器回射的消息(hello world)依然被接收,這導致我們再次發送消息時,從緩沖區中讀出了延遲收到的hello world。

這里只是演示超時技術,因此對此并不做進一步處理。


3 使用SO_RCVTIMEO套接字選項

使用SO_RCVTIMEO套接字選項為recv設置超時

設置方法:

  • 使用setsockopt函數對套接字進行設置
  • 一旦設置了某個描述符,其超時設置將應用于該描述符上的所有讀操作
  • SO_RCVTIMEO僅用于讀操作,SO_SNDTIMEO僅用于寫操作,兩者都不能用于為connect設置超時
  • 如果套接字超時,被阻塞的函數將返回一個EWOULDBLOCK錯誤
void handle_msg(int sockfd) {    char sendbuf[BUFSIZE];    char recvbuf[BUFSIZE + 1];    int n;    struct timeval tv;    tv.tv_sec = 5;    tv.tv_usec = 0;    setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO,               &tv, sizeof(tv) );    while(1) {         memset( sendbuf, '/0', BUFSIZE );        memset( recvbuf, '/0', BUFSIZE );                printf("%s", "send msg:");        gets(sendbuf);        if (strlen(sendbuf) > 0)             send(sockfd,sendbuf,strlen(sendbuf),0);        if ( !strcmp(sendbuf, "exit"))            break;        if ( (n=recv(sockfd,recvbuf,BUFSIZE,0)) < 0 ) {            if (errno == EWOULDBLOCK) {                fprintf(stderr,                        "socket timeout/n");                continue;            }            else                fprintf(stderr,                        "recv error");        }        else{            printf("recv back:%s/n/n", recvbuf);        }    }    close( sockfd );    return;}

運行截圖:

image

可以看到,超時警報成功運行,但依然有上一例中的延遲接收的情況發生,不作處理。


 

示例源碼上傳到了github上,地址:https://github.com/zs634134578/UNP/tree/tryTimeout

 

 

參考資料:

《UNIX網絡編程 卷1:套接字聯網API(第3版)》


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 六盘水市| 陵川县| 绩溪县| 大兴区| 田林县| 交口县| 博兴县| 呈贡县| 文登市| 疏勒县| 黔西| 五大连池市| 綦江县| 勐海县| 博白县| 龙陵县| 织金县| 武冈市| 封开县| 称多县| 晋宁县| 松原市| 辽宁省| 乌兰县| 乐都县| 宁蒗| 澜沧| 武冈市| 稻城县| 安泽县| 且末县| 神池县| 科技| 密山市| 安陆市| 峨眉山市| 佛山市| 东宁县| 镇宁| 罗定市| 玉环县|