前言
本文將講解一對經典的客戶/伺服器回射程式,感受網路程式設計的大致框架( 該程式稍作改裝即可演變成各種提供其他服務的程式 );同時,還將對其執行過程加以分析,觀察程式背後協議的執行細節,學習除錯網路程式的技巧。
客戶端
1 #include "unp.h" 2 3 void str_cli(FILE *fp, int sockfd); 4 5 int 6 main(int argc, char **argv) 7 { 8 int sockfd; 9 struct sockaddr_in servaddr; 10 11 if (argc != 2) 12 err_quit("usage: tcpcli <IPaddress>"); 13 14 sockfd = Socket(AF_INET, SOCK_STREAM, 0); 15 16 bzero(&servaddr, sizeof(servaddr)); 17 servaddr.sin_family = AF_INET; 18 servaddr.sin_port = htons(SERV_PORT); 19 Inet_pton(AF_INET, argv[1], &servaddr.sin_addr); 20 21 Connect(sockfd, (SA *) &servaddr, sizeof(servaddr)); 22 23 str_cli(stdin, sockfd); 24 25 exit(0); 26 } 27 28 /* 29 * 事務函式 30 */ 31 void 32 str_cli(FILE *fp, int sockfd) 33 { 34 char sendline[MAXLINE], recvline[MAXLINE]; 35 36 // 從標準輸入讀取字串( 阻塞於使用者 ) 37 while (Fgets(sendline, MAXLINE, fp) != NULL) { 38 39 // 往緩衝區寫入字串 40 Writen(sockfd, sendline, strlen(sendline)); 41 42 // 從緩衝區讀取字串( 阻塞於伺服器傳回的資料 ) 43 if (Readline(sockfd, recvline, MAXLINE) == 0) 44 err_quit("str_cli: server terminated prematurely"); 45 46 // 讀取從伺服器回射的訊息並在終端列印 47 Fputs(recvline, stdout); 48 } 49 }
伺服器端
1 #include "unp.h" 2 3 void str_echo(int sockfd); 4 5 int 6 main(int argc, char **argv) 7 { 8 int listenfd, connfd; 9 pid_t childpid; 10 socklen_t clilen; 11 struct sockaddr_in cliaddr, servaddr; 12 13 listenfd = Socket(AF_INET, SOCK_STREAM, 0); 14 15 bzero(&servaddr, sizeof(servaddr)); 16 servaddr.sin_family = AF_INET; 17 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 18 servaddr.sin_port = htons(SERV_PORT); 19 20 Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); 21 22 Listen(listenfd, LISTENQ); 23 24 for ( ; ; ) { 25 clilen = sizeof(cliaddr); 26 connfd = Accept(listenfd, (SA *) &cliaddr, &clilen); 27 28 if ( (childpid = Fork()) == 0) { /* 子程式處理段 */ 29 Close(listenfd); /* 關閉監聽套接字 */ 30 str_echo(connfd); /* 事務處理 */ 31 exit(0); 32 } 33 Close(connfd); /* 父程式關閉連線套接字 */ 34 } 35 } 36 37 /* 38 * 事務處理函式 39 */ 40 void 41 str_echo(int sockfd) 42 { 43 ssize_t n; 44 char buf[MAXLINE]; 45 46 again: 47 while ( (n = read(sockfd, buf, MAXLINE)) > 0) 48 Writen(sockfd, buf, n); 49 50 if (n < 0 && errno == EINTR) 51 goto again; 52 else if (n < 0) 53 err_sys("str_echo: read error"); 54 }