第二十二篇:基於UDP的一對回射客戶/伺服器程式

穆晨發表於2017-05-19

前言

       之前曾經學習過一對回射客戶/伺服器程式的例子,不過那個是基於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套接字才能收到異常資訊。

相關文章