第二十二篇:基于UDP的一对回射客户/服务器程序

前言

       之前曾经学习过一对回射客户/服务器程序的例子,不过那个是基于TCP协议的。本文将讲解另一对回射客户/服务器程序,该程序基于UDP协议。

       由于使用的协议不同,因此编写出的程序也有本质上的区别,应将它们对比来进行理解。

通信框架

       

服务器端

 1 #include    "unp.h"
 2 
 3 int
 4 main(int argc, char **argv)
 5 {
 6     int                    sockfd;
 7     struct sockaddr_in    servaddr, cliaddr;
 8 
 9     // 创建UDP套接字
10     sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
11 
12     bzero(&servaddr, sizeof(servaddr));
13     servaddr.sin_family      = AF_INET;
14     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
15     servaddr.sin_port        = htons(SERV_PORT);
16 
17     Bind(sockfd, (SA *) &servaddr, sizeof(servaddr));
18 
19     dg_echo(sockfd, (SA *) &cliaddr, sizeof(cliaddr));
20 }
 1 #include    "unp.h"
 2 
 3 void
 4 dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)
 5 {
 6     int            n;
 7     socklen_t    len;
 8     char        mesg[MAXLINE];
 9 
10     for ( ; ; ) {
11         len = clilen;
12         // 接收数据
13         n = Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);
14 
15         // 回射数据
16         Sendto(sockfd, mesg, n, 0, pcliaddr, len);
17     }
18 }

客户端

 1 #include    "unp.h"
 2 
 3 int
 4 main(int argc, char **argv)
 5 {
 6     int                    sockfd;
 7     struct sockaddr_in    servaddr;
 8 
 9     if (argc != 2)
10         err_quit("usage: udpcli <IPaddress>");
11 
12     bzero(&servaddr, sizeof(servaddr));
13     servaddr.sin_family = AF_INET;
14     servaddr.sin_port = htons(SERV_PORT);
15     Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
16 
17     // 创建UDP套接字
18     sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
19 
20     dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr));
21 
22     exit(0);
23 }
 1 #include    "unp.h"
 2 
 3 void
 4 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
 5 {
 6     int                n;
 7     char            sendline[MAXLINE], recvline[MAXLINE + 1];
 8     socklen_t        len;
 9     struct sockaddr    *preply_addr;
10 
11     preply_addr = Malloc(servlen);
12 
13     while (Fgets(sendline, MAXLINE, fp) != NULL) {
14 
15         // 往服务器发送数据
16         Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);
17 
18         len = servlen;
19         n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);
20         // 不接收非指定服务器的数据
21         if (len != servlen || memcmp(pservaddr, preply_addr, len) != 0) {
22             printf("reply from %s (ignored)\n",
23                     Sock_ntop(preply_addr, len));
24             continue;
25         }
26 
27         // 将回射结果打印给用户
28         recvline[n] = 0;    /* null terminate */
29         Fputs(recvline, stdout);
30     }
31 }

 

小结

1. UDP的机制比起TCP来说,简单多了。但也因此缺少了重传机制,验证相应是否来自对端等等可靠性相关的性质。

2. 只有被 connect 后的UDP套接字才能收到异常信息。

posted @ 2017-05-19 14:02  穆晨  阅读(716)  评论(0编辑  收藏  举报