给UDP增加可靠性

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

给UDP增加可靠性


刺猬@http://blog.csdn.net/littlehedgehog

 

 

 

UNP里面的例子程序,把计算rtt的算法改了下,参考的TCP/IP详解里面介绍的一个稍微简单的算法,另外,不喜欢setjmp这种编程模式,感觉程序代码可读性较差,最后还是改成使用pselect+signal,这样代码会清晰些。

下面是主函数

  1. #include "./unix.h"  
  2. #include "./rtt.h"  
  3. static int  rttinit;  
  4. static struct r_info rtt;  
  5. static struct udphdr  
  6. {  
  7.     unsigned seq;   /* sequence */  
  8.     unsigned ts;        /* timestamp/ms */  
  9. }hdr_send, hdr_recv;  
  10. static void alarm_handler(int signo)  
  11. {  
  12.     return;  
  13. }  
  14. ssize_t send_recv(int sockfd, void *sendbuff, size_t sendbytes, void *recvbuff, size_t recvbytes, const struct sockaddr *praddr, socklen_t len)  
  15. {  
  16.     ssize_t             ret;  
  17.     int                 maxfd;  
  18.     struct timeval      tv;  
  19.     fd_set              rset;  
  20.     struct sigaction    sa;  
  21.     sigset_t            sigset_alarm, sigset_empty;  
  22.     struct msghdr       msg_send, msg_recv;  
  23.     struct iovec        iov_send[2], iov_recv[2];  
  24.     if (!rttinit)  
  25.     {  
  26.         rttinit = 1;  
  27.         rtt_init(&rtt);  
  28.     }  
  29.     memset(&msg_send, 0x00, sizeof(struct msghdr));  
  30.     memset(&msg_recv, 0x00, sizeof(struct msghdr));  
  31.     iov_send[0].iov_base    = &hdr_send;      
  32.     iov_send[0].iov_len     = sizeof(struct udphdr);  
  33.     iov_send[1].iov_base    = sendbuff;  
  34.     iov_send[1].iov_len     = sendbytes;  
  35.     iov_recv[0].iov_base    = &hdr_recv;  
  36.     iov_recv[0].iov_len     = sizeof(struct udphdr);  
  37.     iov_recv[1].iov_base    = recvbuff;  
  38.     iov_recv[1].iov_len     = recvbytes;  
  39.     msg_send.msg_name       = praddr;  
  40.     msg_send.msg_namelen    = len;  
  41.     msg_send.msg_iov        = iov_send;  
  42.     msg_send.msg_iovlen     = 2;  
  43.     msg_recv.msg_name       = praddr;  
  44.     msg_recv.msg_namelen    = len;  
  45.     msg_recv.msg_iov        = iov_recv;  
  46.     msg_recv.msg_iovlen     = 2;  
  47.     hdr_send.seq++;         /* 该次数据包发送序列号 */  
  48.     sigemptyset(&sigset_alarm);  
  49.     sigemptyset(&sigset_empty);  
  50.     sigaddset(&sigset_alarm, SIGALRM);  
  51.     sa.sa_handler           = alarm_handler;  
  52.     sa.sa_flags             = 0;  
  53.     sigemptyset(&sa.sa_mask);  
  54.     if (sigaction(SIGALRM, &sa, NULL) < 0)  
  55.     {  
  56.         perror("sigaction");  
  57.         return;  
  58.     }  
  59.     rtt_newpack(&rtt);  
  60.     FD_ZERO(&rset);  
  61.     for ( ; ; )  
  62.     {  
  63.         hdr_send.ts = rtt_timestamp(&rtt);  
  64.         if ((ret = sendmsg(sockfd, &msg_send, 0)) < 0)  
  65.         {  
  66.             perror("sendmsg");  
  67.             return;  
  68.         }  
  69.         alarm(rtt_start(&rtt));  
  70. loop:  
  71.         FD_SET(sockfd, &rset);  
  72.         sigprocmask(SIG_BLOCK, &sigset_alarm, NULL);  
  73.         if ((ret = pselect(sockfd+1, &rset, NULL, NULL, NULL, &sigset_empty)) < 0)  
  74.         {  
  75.             if (errno == EINTR)  
  76.             {  
  77.                 if (rtt_timeout(&rtt) < 0)       /* limit */  
  78.                 {  
  79.                     rttinit = 0;  
  80.                     errno = ETIMEDOUT;  
  81.                     return (-1);  
  82.                 }  
  83.                 /* send again */  
  84.                 continue;  
  85.             }  
  86.         }  
  87.         if (FD_ISSET(sockfd, &rset))  
  88.         {  
  89.             if ((ret = recvmsg(sockfd, &msg_recv, 0)) < 0)  
  90.             {  
  91.                 perror("recvmsg");  
  92.                 goto loop;  
  93.             }  
  94.             if (ret < sizeof(struct udphdr) || hdr_recv.seq != hdr_send.seq)  
  95.             {  
  96.                 goto loop;  
  97.             }  
  98.             rtt_stop(&rtt, hdr_send.ts);  
  99.             return ret-sizeof(struct udphdr);  
  100.         }  
  101.     }  
  102. }  
  103. void echo(int sockfd, struct sockaddr *praddr, socklen_t len, struct FILE *fp)  
  104. {  
  105.     int         ret;  
  106.     char        sendline[MAXLINE], recvline[MAXLINE];  
  107.     memset(sendline, 0x00, MAXLINE);  
  108.     memset(recvline, 0x00, MAXLINE);  
  109.     while (fgets(sendline, MAXLINE, fp) != NULL)  
  110.     {  
  111.         if ((ret = send_recv(sockfd, sendline, strlen(sendline), recvline, MAXLINE, praddr, len)) < 0)  
  112.         {  
  113.             return;  
  114.         }  
  115.         recvline[ret] = 0;  
  116.         fputs(recvline, stdout);  
  117.     }  
  118. }  
  119. int main(int argc, char *argv[])  
  120. {  
  121.     int connfd;  
  122.     struct sockaddr_in servaddr;  
  123.     if ((connfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)  
  124.     {  
  125.         perror("socket");  
  126.         exit(-1);  
  127.     }  
  128.     memset(&servaddr, 0x00, sizeof(servaddr));  
  129.     servaddr.sin_family = AF_INET;  
  130.     servaddr.sin_port = htons(1988);  
  131.     servaddr.sin_addr.s_addr = inet_addr("210.32.34.137");  
  132.     echo(connfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in), stdin);  
  133.     close(connfd);  
  134.     return 0;  
  135. }   
#include "./unix.h"#include "./rtt.h"static int rttinit;static struct r_info rtt;static struct udphdr{    unsigned seq; /* sequence */    unsigned ts;  /* timestamp/ms */}hdr_send, hdr_recv;static void alarm_handler(int signo){    return;}ssize_t send_recv(int sockfd, void *sendbuff, size_t sendbytes, void *recvbuff, size_t recvbytes, const struct sockaddr *praddr, socklen_t len){    ssize_t    ret;    int     maxfd;    struct timeval  tv;    fd_set    rset;    struct sigaction sa;    sigset_t   sigset_alarm, sigset_empty;    struct msghdr  msg_send, msg_recv;    struct iovec  iov_send[2], iov_recv[2];    if (!rttinit)    {        rttinit = 1;        rtt_init(&rtt);    } memset(&msg_send, 0x00, sizeof(struct msghdr)); memset(&msg_recv, 0x00, sizeof(struct msghdr));    iov_send[0].iov_base = &hdr_send;  iov_send[0].iov_len  = sizeof(struct udphdr);    iov_send[1].iov_base = sendbuff;    iov_send[1].iov_len  = sendbytes;    iov_recv[0].iov_base = &hdr_recv;    iov_recv[0].iov_len  = sizeof(struct udphdr);    iov_recv[1].iov_base = recvbuff;    iov_recv[1].iov_len  = recvbytes;    msg_send.msg_name  = praddr;    msg_send.msg_namelen = len;    msg_send.msg_iov  = iov_send;    msg_send.msg_iovlen  = 2;    msg_recv.msg_name  = praddr;    msg_recv.msg_namelen = len;    msg_recv.msg_iov  = iov_recv;    msg_recv.msg_iovlen  = 2;    hdr_send.seq++;   /* 该次数据包发送序列号 */    sigemptyset(&sigset_alarm);    sigemptyset(&sigset_empty);    sigaddset(&sigset_alarm, SIGALRM);    sa.sa_handler   = alarm_handler;    sa.sa_flags    = 0;    sigemptyset(&sa.sa_mask);    if (sigaction(SIGALRM, &sa, NULL) < 0)    {        perror("sigaction");        return;    }    rtt_newpack(&rtt);    FD_ZERO(&rset);    for ( ; ; )    {        hdr_send.ts = rtt_timestamp(&rtt);        if ((ret = sendmsg(sockfd, &msg_send, 0)) < 0)        {            perror("sendmsg");            return;        }        alarm(rtt_start(&rtt));loop:        FD_SET(sockfd, &rset);        sigprocmask(SIG_BLOCK, &sigset_alarm, NULL);        if ((ret = pselect(sockfd+1, &rset, NULL, NULL, NULL, &sigset_empty)) < 0)        {            if (errno == EINTR)            {                if (rtt_timeout(&rtt) < 0)  /* limit */                {                    rttinit = 0;                    errno = ETIMEDOUT;                    return (-1);                }                /* send again */                continue;            }        }        if (FD_ISSET(sockfd, &rset))        {            if ((ret = recvmsg(sockfd, &msg_recv, 0)) < 0)            {                perror("recvmsg");                goto loop;            }            if (ret < sizeof(struct udphdr) || hdr_recv.seq != hdr_send.seq)            {                goto loop;            }            rtt_stop(&rtt, hdr_send.ts);            return ret-sizeof(struct udphdr);        }    }}void echo(int sockfd, struct sockaddr *praddr, socklen_t len, struct FILE *fp){    int   ret;    char  sendline[MAXLINE], recvline[MAXLINE];    memset(sendline, 0x00, MAXLINE);    memset(recvline, 0x00, MAXLINE);    while (fgets(sendline, MAXLINE, fp) != NULL)    {        if ((ret = send_recv(sockfd, sendline, strlen(sendline), recvline, MAXLINE, praddr, len)) < 0)        {            return;        }        recvline[ret] = 0;        fputs(recvline, stdout);    }}int main(int argc, char *argv[]){    int connfd;    struct sockaddr_in servaddr;    if ((connfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)    {        perror("socket");        exit(-1);    }    memset(&servaddr, 0x00, sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(1988);    servaddr.sin_addr.s_addr = inet_addr("210.32.34.137");    echo(connfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in), stdin);    close(connfd);    return 0;} 

rtt.c

  1. #include "./unix.h"  
  2. #include "./rtt.h"  
  3. #define MAXXMT      4  
  4. void rtt_init(struct r_info *rtt)  
  5. {  
  6.     struct timeval  tv;  
  7.     gettimeofday(&tv, NULL);  
  8.     rtt->r_tbase = tv;  
  9.     rtt->r_rtt       = 0;  
  10.     rtt->r_rto       = 3;  
  11. }  
  12. void rtt_newpack(struct r_info *rtt)  
  13. {  
  14.     rtt->r_rexmt = 0;  
  15. }  
  16. int rtt_start(struct r_info *rtt)  
  17. {  
  18.     return (int)rtt->r_rto;  
  19. }  
  20. unsigned rtt_timestamp(struct r_info *rtt)  
  21. {  
  22.     struct timeval  tv;  
  23.     gettimeofday(&tv, NULL);  
  24.     return (tv.tv_sec-rtt->r_tbase.tv_sec)*1000+(tv.tv_usec-rtt->r_tbase.tv_usec)/1000;  
  25. }  
  26. void rtt_time(struct r_info *rtt, struct timeval *tv)  
  27. {  
  28.     tv->tv_sec = rtt->r_rto;  
  29.     tv->tv_usec = 0;  
  30.     return;  
  31. }  
  32. int rtt_timeout(struct r_info *rtt)  
  33. {  
  34.     rtt->r_rto *= 2;  
  35.     if (++rtt->r_rexmt > MAXXMT)  
  36.         return (-1);  
  37.     return 0;  
  38. }  
  39. void rtt_stop(struct r_info *rtt, unsigned sendts)  
  40. {  
  41.     float temp = (rtt_timestamp(rtt)-sendts)/1000;  
  42.     rtt->r_rtt = rtt->r_rtt*0.9 + temp*0.1;  
  43.     rtt->r_rto = rtt->r_rtt*2;  
  44. }  
#include "./unix.h"#include "./rtt.h"#define MAXXMT  4void rtt_init(struct r_info *rtt){    struct timeval tv;    gettimeofday(&tv, NULL);    rtt->r_tbase = tv;    rtt->r_rtt  = 0;    rtt->r_rto  = 3;}void rtt_newpack(struct r_info *rtt){    rtt->r_rexmt = 0;}int rtt_start(struct r_info *rtt){    return (int)rtt->r_rto;}unsigned rtt_timestamp(struct r_info *rtt){    struct timeval tv;    gettimeofday(&tv, NULL);    return (tv.tv_sec-rtt->r_tbase.tv_sec)*1000+(tv.tv_usec-rtt->r_tbase.tv_usec)/1000;}void rtt_time(struct r_info *rtt, struct timeval *tv){    tv->tv_sec = rtt->r_rto;    tv->tv_usec = 0;    return;}int rtt_timeout(struct r_info *rtt){    rtt->r_rto *= 2;    if (++rtt->r_rexmt > MAXXMT)        return (-1);    return 0;}void rtt_stop(struct r_info *rtt, unsigned sendts){    float temp = (rtt_timestamp(rtt)-sendts)/1000;    rtt->r_rtt = rtt->r_rtt*0.9 + temp*0.1;    rtt->r_rto = rtt->r_rtt*2;}



           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_43678612/article/details/84071420