この記事では、単純なTCPソケットハーフクローズ知識について説明します。
一般的に、TCPコネクションの確立が、この時点でのデータ交換を開始していないため、比較的安定であり、データ交換が発生したためと切断手順、いくつかのケースではかもしれない予想外のことが起こりました。
接続によって引き起こさ片側断線の問題
内容以前に述べたように、我々は直接データを受け取ることができなくなり、地元の両端には、もはやデータを送信できることをどの手段、クローズ機能が完全に切断されている呼び出しません。この目的のためにはもはや単なるデータを送信したい場合は、また、直接危機一髪完全に、それは非常にエレガントではなかったから切り離され、データを受信することはできません。したがって、我々は、(半近い)方式「の交換に使用されるデータ・ストリームの閉じた部分のみ」を必要とします。
一方的に切断
ソケットおよびストリーム(ストリーム)
二つのホストとしても知られているデータ交換ソケット接続、入力した後の状態を確立するための「フロー状態が形成されます。」各ホストは、別の入力を有し、出力ストリーム、及び入力と出力ストリームとストリーム側は2つのI / Oストリームに一致するように形成されています。
私は2つのソケット/ Oストリームを形成しました
エレガントな切断シャットダウン機能のために
シャットダウンは、双方向I / Oストリームを切断するために使用しました。
書式#include <sysの/ socket.h>に int型のシャットダウン(int型私たちの靴下、int型のHOWTOを); - > 0を返すの成功、失敗を返します- 。1
第2のストリーミングモードパラメータは切断を決定します。
- SHUT_RD:入力ストリームを切断
- SHUT_WR:出力ストリームを切断
- SHUT_RDWR:同時に両方のI / Oストリームを切断
いわゆる切断フローは、実際には、ソケットの間の通路は、I / Oバッファを切り離します。ソケットがデータを送信することができない、出力ストリームオフSHUT_WRが、しかし、このように、SHUT_RD入力ストリームを切断し、ソケットは、受信されたデータ入力バッファが消去され、入力は、関連する関数を呼び出すことができない場合でも、データを受信することができません出力バッファが残っている場合、データはまだ先ホストに送信することができます。
なぜあなたは、ハーフクローズが必要なのか
セミクローズドの主な役割は二つあります。その他、本発明の端場合は、まず、反対側を可能にするために、ターゲットホストへのデータ送信の信号(EOF)エンドを送信する送信データが存在していたが、他のアクション(この関数はまた、クローズ動作を行うことができる)とすることができる感知データ送信はまた、唯一の出力ストリームをフィードバック情報端末、コールシャットダウン機能をオフに受信する必要が完了した後(半閉じ、それがクローズ機能を達成することができません)。
セミクローズドファイル転送プログラム
次のプログラムは、ファイル転送の接合部に基づいており、ハーフクローズハーフクローズアクションのシャットダウンを表示するために行います。
図トランスポートストリームファイル
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h> 5 #include <arpa/inet.h> 6 #include <sys/socket.h> 7 8 #define BUF_SIZE 30 9 void error_handling(char *message); 10 11 int main(int argc, char *argv[]) 12 { 13 int serv_sd, clnt_sd; 14 FILE * fp; 15 char buf[BUF_SIZE]; 16 int read_cnt; 17 18 struct sockaddr_in serv_adr, clnt_adr; 19 socklen_t clnt_adr_sz; 20 21 if(argc!=2) { 22 printf("Usage: %s <port>\n", argv[0]); 23 exit(1); 24 } 25 26 fp=fopen("file_server.c", "rb"); 27 serv_sd=socket(PF_INET, SOCK_STREAM, 0); 28 29 memset(&serv_adr, 0, sizeof(serv_adr)); 30 serv_adr.sin_family=AF_INET; 31 serv_adr.sin_addr.s_addr=htonl(INADDR_ANY); 32 serv_adr.sin_port=htons(atoi(argv[1])); 33 34 bind(serv_sd, (struct sockaddr*)&serv_adr, sizeof(serv_adr)); 35 listen(serv_sd, 5); 36 37 clnt_adr_sz=sizeof(clnt_adr); 38 clnt_sd=accept(serv_sd, (struct sockaddr*)&clnt_adr, &clnt_adr_sz); 39 40 while(1) 41 { 42 read_cnt=fread((void*)buf, 1, BUF_SIZE, fp); 43 if(read_cnt<BUF_SIZE) 44 { 45 write(clnt_sd, buf, read_cnt); 46 break; 47 } 48 write(clnt_sd, buf, BUF_SIZE); 49 } 50 51 shutdown(clnt_sd, SHUT_WR); 52 read(clnt_sd, buf, BUF_SIZE); 53 printf("Message from client: %s \n", buf); 54 55 fclose(fp); 56 close(clnt_sd); close(serv_sd); 57 return 0; 58 } 59 60 void error_handling(char *message) 61 { 62 fputs(message, stderr); 63 fputc('\n', stderr); 64 exit(1); 65 }
运行结果