閉じられたソケットに対して、
クライアントから書き込みを行った場合どんな結果になるのでしょうか?
その場合、サーバからRSTパケットが送信されることになります。
続いて、RSTを受信したソケットに対して、
クライアントが書き込みを行うとどんな結果になるのでしょうか?
その場合、クライアント側プロセスで、SIGPIPEシグナルが発生します。
今回は、daytimeサーバと、サーバへ文字列を送信するクライアントで実験してみます。
起動
daytimeサーバ、クライアントそれぞれ別ホストで起動
daytimeサーバ(192.168.11.6):
普通のubuntuディストリビューションでは自動に起動されてるハズ。
クライアント(192.168.11.11):
daytimeサーバアドレスを指定して起動
動作説明
クライアント動作:コネクションを確立した後、2秒スリープ。
サーバ側動作:2秒スリープしている間に、サーバ側はコネクションをクロース
クライアント動作:その後、ソケットに、文字列"test"を書き込む。
サーバ動作:
クローズされたコネクションへ書き込みされるので、このタイミングで、
クライアント側へRSTを送信
クライアント側動作:2秒スリープ(サーバからのRSTを確実に受信するため)
クライアント側動作:ソケットに、文字列"test2"を書き込む。シグナルSIGPIPE発生!
結果
wiresharkでのパケットダンプ
No.52〜No.54は、3wayハンドシェーク(クライアント側は、この後すぐさま2秒スリープ)
No.55〜No.56は、daytimeサーバとクライアント間でそれぞれ時刻データ送信、ACK応答
No.57は、daytimeサーバからのFIN,ACK
No.58は、クライアントからのACK
No.59は、クライアントからソケットへの1度目の書き込み(daytimeサーバによってクローズされたソケット)
その後、2秒スリープ
No.58は、daytimeサーバからのRST
その後、クライアント側プロセスで、ソケットへの2度目の書き込み
このタイミングで、クライアント側プロセスでSIGPIPE発生。
ターミナルの出力
シグナルSIGPIPEをハンドリング。 signo = 13(SIGPIPE)を検出している。
SIGPIPEの定義は、
Man page of SIGNAL
http://linuxjm.sourceforge.jp/html/LDP_man-pages/man7/signal.7.html
より13であることを確認。
client
#include "unp.h"
void sigpipe(int signo);
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(13);
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
Signal(SIGPIPE, sigpipe);
Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));
sleep(2);
Write(sockfd, "test", 4);
sleep(2);
Write(sockfd, "test2", 5);
exit(0);
}
void sigpipe(int signo)
{
printf("This Handler received SIGPIPE %d\n", signo);
return;
}