亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Unix網絡編程—— shutdown與close

2019-11-06 07:24:33
字體:
來源:轉載
供稿:網友

TCP的連接終止序列

TCP建立一個連接需要三次握手,但是終止一個連接需要四次揮手: 1. 當某個應用進程主動調用close時,它向對端發送一個FIN分節,表示這端需要關閉連接 2. 當對端接收到FIN分節時,read函數返回0,它的TCP發送一個ACK,表示接收到了主動close端的FIN分節。主動關閉端的TCP在接受到ACK后處于FIN_WAIT狀態,表示需要等待對端的FIN分節到達。 3. 被動關閉端發送FIN分節給主動關閉端,主動關閉端收到FIN后,發送ACK給對端,處于TIME_WAIT狀態,表示等待被動關閉端的ACK確認 4. 被動關閉端接收到ACK后四次揮手完成,兩端套接字關閉完成 TCP四次揮手

close函數

#include <unistd.h>int close(int fd);// 成功返回0,失敗返回-1,并且置位errno

close在TCP中的默認行為是把該套接字標記為已關閉,然后立即返回到調用進程。該套接字描述符不能再由調用進程使用,也就是不能再作為read,write的第一個參數。然而TCP將嘗試發送已排隊等待發送到對端的任何數據,發送完畢后再發送TCP連接終止序列。

close的錯誤返回三種情況: - EBADF:表示參數fd為非法描述符 - EINTR:close調用被信號中斷 - EIO:I/O時出現錯誤

一個常見的TCP并發服務器模型:

#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>int main(){ int sockfd = socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in serv_addr; struct sockaddr_in client_addr; int client_len; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(LISTEN_PORT); serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); int ret = bind(sockfd,(struct sockaddr* )&serv_addr,sizeof(serv_addr)); ret = listen(sockfd,LISTENQ); while(1){ client_len = sizeof(client_addr); int client_fd = accept(sockfd,(struct sockaddr *)&client_addr,&client_len); pid_t pid = fort(); if(pid < 0){ continue; } else if(pid == 0){ do_serv(); close(); } else close(client_fd); } return 0;}

上述代碼中close被調用2次,因為子進程和父進程共享了client_fd,其引用計數為2,如果子進程只調用一次,則會導致client_fd的套接字永遠不能關閉,導致進程描述符耗盡而無法為其他請求提供服務。并且當close調用時,TCP的讀寫2端都被關閉。

close在網絡編程中的局限: - 當一個描述符被共享使用時,調用close函數只是將其引用計數減一,僅僅在引用計數為0的時候,該套接字才被關閉。 - close終止讀和寫2個方向的數據傳輸。TCP為全雙工協議,有時候當我們完成數據發送后,可能需要等待對端發送數據,此時可以調用shutdown來實現此功能。

shutdown函數

int shutdown(int sockfd,int howto); //返回:成功返回0,失敗返回-1

howto的可選項: SHUT_RD:關閉連接的讀——套接字中不再讀取數據,而且套接字接受緩沖區中的數據也會被丟棄。進程不能再對這個套接字調用任何讀取函數。 SHUT_WR:關閉連接的寫——對于TCP套接字,這成為半關閉。當前留在套接字發送緩沖區中的數據將被發送掉,然后TCP的正常連接終止序列。無論這個套接字描述符的引用計數是否為0,shutdown都會激發TCP終止序列,以后進程不能再對這個套接字調用任何寫函數。 SHUT_RDWR:關閉讀、寫——相當于分別調取了shutdown兩次并傳遞參數SHUT_RD和SHUT_WR。shutdown使用此選項與close的區別是,shutdown立馬關閉套接字的讀寫通道,但是close只會在引用計數為0的情況才關閉讀寫通道。

close和shutdown的對比示例

主程序

#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/select.h>#include <arpa/inet.h>#include <netinet/in.h>extern void client_echo(FILE *fp,int sockfd);int main(){ int sockfd = socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in serv_addr; struct sockaddr_in client_addr; int client_len; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(LISTEN_PORT); char *strip = inet_pton(AF_INET,"127.0.0.1",&serv_addr.sin_addr); int ret = connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); client_echo(stdin,sockfd);//從stdin讀取數據發送到sockfd并回寫 return 0;}

使用close的實現

void client_echo(FILE *fp,int sockfd){ if(fp == NULL) return; int fd = fineno(fp); fd_set read_set; FD_ZERO(&read_set); int stdin_eof = 0; int nread = 0; char recvbuf[1024]; while(1){ FD_SET(fd,&read_set); FD_SET(sockfd,&read_set); int maxfd = max(fd,sockfd); int ret = select(maxfd + 1,&read_set,NULL,NULL,NULL); if(ret < 0){ if(errno == EINTR) continue; // 由于中斷引發的失敗,重試 else { // 其他錯誤,退出 perror("select"); return; } } if(FD_ISSET(sockfd,&read_set)){ if( (nread = read(sockfd,recvbuf,sizelf(recvbuf))) == 0){ 在上面的程序中,當客戶端從終端讀取到CTRL+D的時候將使fgets函數返回0,此時引發客戶端主動關閉close,退出客戶端的連接處理函數后,將立即退出程序(main函數結束)。此時服務端如果有數據正在發送,則將會丟失。處理這種問題的方式是,當客戶端不再write時,只關閉TCP的write,但是任然保留其read通道??梢酝ㄟ^shutdown來實現。

使用shutdown的實現

void client_echo(FILE *fp,int sockfd){ if(fp == NULL) return; int fd = fineno(fp); fd_set read_set; FD_ZERO(&read_set); int stdin_eof = 0; int nread = 0; char recvbuf[1024]; int maxfd; while(1){ FD_SET(fd,&read_set); FD_SET(sockfd,&read_set); if(stdin_eof != 0){ FD_CLR(fd,&read_set); maxfd = sockfd; } else maxfd = max(fd,sockfd); int ret = select(maxfd + 1,&read_set,NULL,NULL,NULL); if(ret < 0){ if(errno == EINTR) continue; // 由于中斷引發的失敗,重試 else { // 其他錯誤,退出 perror("select"); return; } } if(FD_ISSET(sockfd,&read_set)){ if( (nread = read(sockfd,recvbuf,sizelf(recvbuf))) == 0){ if(stdin_eof == 1){ return; } else{ printf("read EOF from serv/n"); close(sockfd); exit(1); } } fputs(recvbuf,stdout); } if(FD_ISSET(fd,&read_set)){ if(fgets(recvbuf,sizeof(recvbuf),fd) == 0){ stdin_eof = 1; shutdown(sockfd,SHUT_WR); // send FIN FD_CLR(fd,&read_set); } else write(sockfd,recvbuf,strlen(recvbuf)); } }}

在shutdown_client中,當從終端讀取到EOF時,將調用shutdown關閉套接字的寫通道,但是此套接字任然可以從服務端讀取數據,保證了數據不會丟失。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成人精品在线播放| xxx一区二区| 69国产精品成人在线播放| 久久久久久网址| 欧美丰满片xxx777| 国产成人亚洲精品| 中文字幕一区电影| 欧美中文在线观看| 亚洲视频第一页| 国产精品第10页| 国内精品久久久久久中文字幕| 亚洲成人a**站| 97精品在线观看| 欧美福利视频在线| 黑人巨大精品欧美一区二区三区| 韩国美女主播一区| 亚洲午夜小视频| 青草成人免费视频| 久久久亚洲国产| 欧美激情中文字幕在线| 久久久久国产精品www| 亚洲精品久久久久中文字幕欢迎你| 在线观看日韩欧美| 国产精品中文字幕久久久| 久久伊人精品一区二区三区| 欧美大片在线免费观看| 国产在线视频2019最新视频| 欧美成人精品一区| 国产免费一区二区三区在线观看| 欧美放荡办公室videos4k| 亚洲欧美日韩成人| 色综合91久久精品中文字幕| 国产精品国模在线| 日本三级久久久| 91影视免费在线观看| 国产精品白嫩初高中害羞小美女| 国产福利视频一区二区| 国产精品久久久久久久久久免费| 欧美激情视频免费观看| 日韩在线观看你懂的| 亚洲人成网站色ww在线| 国产亚洲欧美aaaa| 亚洲人成在线一二| www.亚洲成人| 欧美亚洲在线播放| 精品一区电影国产| 亚洲а∨天堂久久精品9966| 不卡中文字幕av| 亚洲www视频| 亚洲在线视频福利| 亚洲精品日韩av| 国产精品视频精品| 日韩va亚洲va欧洲va国产| 69av在线视频| 国产91色在线播放| 欧美在线视频免费观看| 精品国产1区2区| 国产精品日韩久久久久| 久久国产精品久久久久久久久久| 色噜噜亚洲精品中文字幕| 久久在线免费观看视频| 国产成人在线亚洲欧美| 国产98色在线| 国产精品视频xxxx| 亚洲第一网中文字幕| 国产精品第1页| 欧美成人午夜剧场免费观看| 国产午夜精品免费一区二区三区| 日韩中文字幕在线免费观看| 国产精品中文字幕久久久| 日韩视频精品在线| 不卡av日日日| 亚洲偷熟乱区亚洲香蕉av| 国内精品一区二区三区四区| 欧美老少做受xxxx高潮| 日本欧美一级片| 久久成人在线视频| 日本不卡高字幕在线2019| 久久精品国产欧美激情| 日韩经典中文字幕在线观看| 欧美午夜丰满在线18影院| 国产高清在线不卡| 中文字幕日韩av| 久久亚洲成人精品| 国产在线拍揄自揄视频不卡99| 国产精品久久久久久久久免费看| 国产免费亚洲高清| 亚洲va电影大全| 日本久久精品视频| 欧美成年人视频网站| 一区二区三区四区视频| 国产精品久久久一区| 欧美刺激性大交免费视频| 国产精品久久久久久久一区探花| 欧美日韩精品在线| 亚洲视频自拍偷拍| 4k岛国日韩精品**专区| 久久国产精品影视| 日韩精品在线免费观看视频| 高清日韩电视剧大全免费播放在线观看| 日韩有码在线播放| 久久亚洲欧美日韩精品专区| 欧美性xxxxxx| 国产欧美一区二区白浆黑人| 久久99精品国产99久久6尤物| 一本色道久久综合亚洲精品小说| 97久久精品人搡人人玩| 日本一区二区不卡| 国产精品三级在线| 欧美日韩国产色视频| 亚洲一区二区三区四区视频| 亚洲欧美日韩直播| 精品一区二区三区四区| 精品久久久久久久久久久久| 在线看片第一页欧美| 亚洲欧美激情精品一区二区| 国产精品久久久久99| 久久亚洲春色中文字幕| 亚洲丁香久久久| www.99久久热国产日韩欧美.com| 亚洲欧洲中文天堂| 欧美一区二区影院| 亚洲一区免费网站| 国产日韩中文字幕在线| 亚洲老头老太hd| 91亚洲永久免费精品| 久久精品国产成人| 亚洲性生活视频在线观看| 国产精品久久91| 国产精品露脸av在线| 亚洲区一区二区| 国产成人精品免高潮费视频| 欧美亚洲午夜视频在线观看| 精品久久久久久国产91| 日韩欧美在线国产| 日韩免费av片在线观看| 日韩美女在线观看一区| 国产欧美日韩视频| 中文字幕亚洲一区二区三区| 成人在线精品视频| 欧美大片va欧美在线播放| 亚洲午夜av电影| 美女视频久久黄| 欧美精品精品精品精品免费| 55夜色66夜色国产精品视频| 久久精品99久久香蕉国产色戒| 成人激情视频网| 日韩大片在线观看视频| 国产伊人精品在线| 亚洲欧美中文日韩在线| 欧美在线视频观看免费网站| 国产精品成人在线| 欧美成人全部免费| 久久精品国产久精国产一老狼| 亚洲欧美日韩国产成人| 亚洲色图欧美制服丝袜另类第一页| 亚洲aaa激情| 欧美视频专区一二在线观看| 欧美大片第1页| 亚洲美女视频网| 国产精品久久久久久搜索| 国产综合在线观看视频| 成人亚洲综合色就1024| 亚洲香蕉成人av网站在线观看|