Eukleides project

from http://d.hatena.ne.jp/u5_h/

(tcp/ip関連)TCPのTIME_WAIT状態の実験

まずは単純な文字列をループバック(127.0.0.1)で送る送受信プログラムを作る。
比較のためにSTREAM型(TCP)とDATAGRAM型(UDP)の送受信プログラムを用意する

//DATAGRAM型(UDP)の文字列受信サーバプログラム
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define PORT 12345

int main( void )
{
int s;
if ((s=socket( AF_INET, SOCK_DGRAM, 0 ))<0)
{
perror("socket");
exit(1);
}
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY);
addr.sin_port=htons(PORT);
if((bind( s,(struct sockaddr*)&addr, sizeof addr))<0)
{
perror("bind");
exit(1);
}
char buf[16];
int len;
len = recvfrom( s, buf, sizeof buf, 0, NULL, NULL );
buf[len] = '\0';
printf("Server received : %s\n", buf );
close(s);
return 0;
}

//DATAGRAM型(UDP)の文字列送信クライアントプログラム

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define PORT 12345
#define HOST "127.0.0.1"

int main( void )
{
int s;
if((s=socket( AF_INET, SOCK_DGRAM, 0 ))<0)
{
perror("socket");
exit(1);
}
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(HOST);
addr.sin_port=htons(PORT);
char buf[16] = "This is client.";
sendto( s, buf, strlen(buf), 0,(structsockaddr*)&addr,sizeof addr);
close(s);
return 0;
}

STREAM型(TCP)の文字列受信サーバプログラム

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define PORT 12345

int main( void )
{
int s,ss;
if((s=socket( AF_INET, SOCK_STREAM, 0 ))<0)
{
perror("socket");
exit(0);
}
struct sockaddr_in sev;

sev.sin_family=AF_INET;
sev.sin_addr.s_addr=htonl(INADDR_ANY);
sev.sin_port=htons(PORT);

if( bind( s, (struct sockaddr*)&sev, sizeof(sev) ) < 0 )
{
perror("bind");
exit(1);
}
if(listen(s,1)<0)
{
perror("listen");
exit(1);
}
if((ss=accept(s,NULL, NULL))<0)
{
perror("accept");
exit(1);
}
char buf[16];
int len;
len = recv( ss, buf, sizeof(buf),0);
buf[len] = '\0';
printf("Server received : %s\n", buf );
close(ss);
close(s);
return 0;
}

STREAM型(TCP)の文字列送信クライアントプログラム

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define PORT 12345
#define HOST "127.0.0.1"

int main( void )
{
int s;
if((s =socket( AF_INET, SOCK_STREAM, 0 ))<0)
{
perror("socket");
exit(1);
}

struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(HOST);
addr.sin_port=htons(PORT);
if((connect(s,(struct sockaddr*)&addr,sizeof addr))<0)
{
perror("connect");
exit(1);
}
char buf[16] = "Hello";
send( s, buf, sizeof(buf), 0);
close(s);
return 0;
}

以上4つのプログラムをコンパイルし、TCP、UDPそれぞれの場合の通信状況をコマンドライン2つ立ち上げ比較してみた。比較検証用にnetstatを用いる。netstatを起動し、サーバ側を立ち上げ、クライアント側を立ち上げるとメッセージが送信される。
結果
DATAGRAM型(UDP)
netstat -usc
(中略)
Udp:
458 個のパケットを受信
165 packets to unknown port received.
10959 packet receive errors
396 個のパケットを送信
Udp:
458 個のパケットを受信
165 packets to unknown port received.
10962 packet receive errors
396 個のパケットを送信
netstat -up
c
稼働中のインターネット接続 (w/oサーバー)
Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状態
稼働中のインターネット接続 (w/oサーバー)
Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状態
稼働中のインターネット接続 (w/oサーバー)
Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状態

STREAM型(TCP)
netstat -tpc
稼働中のインターネット接続 (w/oサーバー)
Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状態 PID/Program name
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
稼働中のインターネット接続 (w/oサーバー)
Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状態 PID/Program name
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
稼働中のインターネット接続 (w/oサーバー)
Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状態 PID/Program name
tcp 0 0 localhost:12345 localhost:1904 TIME_WAIT -
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
稼働中のインターネット接続 (w/oサーバー)
Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状態 PID/Program name
tcp 0 0 localhost:12345 localhost:1904 TIME_WAIT -
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
稼働中のインターネット接続 (w/oサーバー)
Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状態 PID/Program name
tcp 0 0 localhost:12345 localhost:1904 TIME_WAIT -
(中略)2〜3分後元の状態に戻る
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
稼働中のインターネット接続 (w/oサーバー)
Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状 態 PID/Program name
tcp 0 0 localhost:12345 localhost:1904 TIME_WAIT -
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
稼働中のインターネット接続 (w/oサーバー)
Proto 受信-Q 送信-Q 内部アドレス 外部アドレス 状 態 PID/Program name
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)


以上よりTCPのCLOSINGシーケンスにおけるTIME_WAIT状態が確認できる。TCPが通信確保に3wayhandshake方式をとっている例である。