UNP学习第五章
一、概述
想要寫(xiě)一個(gè)完整的TCP客戶-服務(wù)器程序例子,有下面功能的回射服務(wù)器
1.客戶從標(biāo)準(zhǔn)輸入讀一行文本,寫(xiě)到服務(wù)器上;
2.服務(wù)器從網(wǎng)絡(luò)輸入讀此行,并回射給客戶;
3.客戶讀此回射行并寫(xiě)到標(biāo)準(zhǔn)輸出。
此例子需要觀察:正常運(yùn)行時(shí)什么情況,客戶和服務(wù)器都啟動(dòng)時(shí)什么情況,客戶正常終止時(shí)什么情況,
如果服務(wù)器在客戶之前終止客戶什么情況,如果服務(wù)器主機(jī)崩潰則客戶什么情況。
?
二、TCP回射服務(wù)器程序:main函數(shù)
1 #include "unp.h" 2 3 int 4 main(int argc, char *argv[]) 5 { 6 int listenfd, connfd; 7 pid_t childpid; 8 socklen_t clilen; 9 struct sockaddr_in cliaddr, servaddr; 10 11 listenfd = Socket(AF_INET, SOCK_STREAM, 0); 12 13 bzero(&servaddr, sizeof(servaddr)); 14 servaddr.sin_family = AF_INET; 15 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 16 servaddr.sin_port = htons(SERV_PORT); 17 Bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); 18 19 Listen(listenfd, LISTENQ); 20 for(;;) { 21 clilen = sizeof(cliaddr); 22 connfd = Accept(listenfd, (SA *)&cliaddr, &clilen); 23 if((childpid = Fork()) == 0) { /* child process */ 24 Close(listenfd); /* close listening socket */ 25 str_echo(connfd); /* process the request */ 26 exit(0); 27 } 28 Close(connfd); /* parent closes connected socket */ 29 } 30 }?
#include "unp.h"void str_echo(int sockfd) {ssize_t n;char line[MAXLINE];for(;;) {if((n = Readline(sockfd, line, MAXLINE)) == 0)return; /* connection closed by other end */Writen(sockfd, line, n);} }?
三、TCP回射客戶程序:main函數(shù)
#include "unp.h"int main(int argc, char *argv[]) {int sockfd;struct sockaddr_in servaddr;if(argc !=2)err_quit("usage:tcpcli <IPaddress>");sockfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);inet_pton(AF_INET, argv[1], &servaddr.sin_addr);Connect(sockfd, (SA *)&servaddr, sizeof(servaddr));str_cli(stdin, sockfd);exit(0); }str_cli:
#include "unp.h"void str_cli(FILE *fp, int sockfd) {char sendline[MAXLINE], recvline[MAXLINE];while(Fgets(sendline, MAXLINE, fp) != NULL) {Writen(sockfd, sendline, strlen(sendline));if(Readline(sockfd, recvline, MAXLINE) == 0)err_quit("str_cli:server terminated prematurely");Fputs(recvline, stdout);} }?
四、正常終止
正常終止客戶和服務(wù)器的步驟:
1.當(dāng)我們鍵入EOF字符時(shí),fgets返回一個(gè)空指針,于是str_cli返回。
2.當(dāng)str_cli返回到客戶的函數(shù)main時(shí),main通過(guò)調(diào)用exit終止。
3.進(jìn)程終止處理的一部分是關(guān)閉所有打開(kāi)的描述字,所以客戶套接口由內(nèi)核關(guān)閉。
TCP連接終止的前半部分:客戶TCP發(fā)送一個(gè)FIN給服務(wù)器,服務(wù)器TCP則ACK響應(yīng)。
此時(shí),服務(wù)器套接口處于CLOSE_WAIT狀態(tài),客戶套接口處于FIN_WAIT_2狀態(tài)。
4.當(dāng)服務(wù)器TCP接收FIN時(shí),服務(wù)器子進(jìn)程阻塞于readline調(diào)用,于是readline返回0,這導(dǎo)致函數(shù)str_echo返回服務(wù)器子進(jìn)程的main
5.服務(wù)器子進(jìn)程通過(guò)調(diào)用exit來(lái)終止。
6.服務(wù)器子進(jìn)程中打開(kāi)的所有描述字隨之關(guān)閉。由子進(jìn)程來(lái)關(guān)閉已連接套接口引發(fā)TCP連接終止序列的最后兩個(gè)分節(jié):一個(gè)從服務(wù)器到客戶的FIN和一個(gè)從客戶到服務(wù)器的ACK。至此,連接完全終止,客戶套接口進(jìn)入TIME_WAIT狀態(tài)。
7.進(jìn)程終止處理的另一部分是在服務(wù)器子進(jìn)程終止時(shí)給父進(jìn)程發(fā)一個(gè)信號(hào)SIGCHLD。
?
轉(zhuǎn)載于:https://www.cnblogs.com/ch122633/p/8442273.html
與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
                            
                        - 上一篇: 01进制之间的转换
 - 下一篇: mongo笔记 // 一字一句的写下来,