ソケット通信で、サーバプロセスが、killプロセスされた場合、
どのようなパケットが流れるのでしょう?
想像では、
サーバプロセスからクライアントへ、FIN,ACKが送信され、
クライアントからは、ACKをサーバへ返す...というところでしょうか?
(サーバプロセスはkillされてるから意味ないと思うんですが...)
では、その後、クライアントTCP/IPは、FIN,ACKをサーバへ送信するのでしょうか?
エコーサーバ、クライアントを例にとって、パケットを見てみます。
echoサーバ、クライアントを起動し、echoクライアントから文字列をサーバへ送信、
その後、echoサーバプロセスをkill(sudo kill -9 サーバプロセスID)するまでのパケットの様子です。
サーバIPアドレス&ポート:192.168.11.6:9877
クライアントIPアドレス:192.168.11.11
この時点では、クライアントからFIN,ACKは送信されてませんね。
理由は、クライアント側のアプリレイヤに制御があるためです。(ターミナルでユーザの入力待ち)
その後、クライアントターミナルから文字列を入力すると
パケットNo.11445で、データをサーバへ送信、
パケットNo.11446で、FIN,ACKをサーバへ送信、
パケットNo.11447で、サーバからのRST受信という流れになっています。
まぁ、通常のコネクション解放シーケンスにはなっていませんね。
通常ですと、サーバから、ACKが帰ってくるはずなので。
疑問なのは、なぜ、パケットNo.11445でデータをサーバへ投げているのか?があります。
なぜなら既にサーバから、FIN,ACKを受けて、ACK応答しているので、
データ送信しなくてもいいじゃんと思ってしまうのですが...。
echoサーバ
#include "unp.h"
#include "unistd.h"
int
main(int argc, char **argv)
{
int listenfd, connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
void sig_chld(int);
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
Signal(SIGCHLD, sig_chld);
for ( ; ; ) {
clilen = sizeof(cliaddr);
if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) {
if (errno == EINTR)
continue; /* back to for() */
else
err_sys("accept error");
}
if ( (childpid = Fork()) == 0) { /* child process */
Close(listenfd); /* close listening socket */
str_echo(connfd); /* process the request */
Close(connfd);
exit(0);
}
Close(connfd); /* parent closes connected socket */
}
}
echoクライアント
#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);
servaddr.sin_port = htons(9877);
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));
str_cli(stdin, sockfd); /* do it all */
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);
}
}