accept

acceptは接続してきた相手のソケットを受け付けるUNIXシステムコール・・・。

Man page of ACCEPT

listenでリッスンした後にこれを呼ぶと、相手が接続する(アクセプト)まで次の処理にいかない(ブロッキング)・・・。

相手が接続してきたら、引数のaddrに相手のIPアドレスなどの情報、戻り値に相手とやりとりするためのソケットファイルディスクリプタが返され、この関数を抜ける・・・。

この返された情報をもとに接続相手に対する通信処理をする・・・。

接続してきた相手のIPなどの情報を出力するサーバを作る・・・。

クライアントを識別するソケットファイルディスクリプタはacc、IPアドレスや、ポートなどの情報はclient_addrに格納することにする・・・。

サーバソケットの作成から、リッスンまで・・・。

acceptの3つ目の引数にclient_addrのサイズを渡すので、client_addr_lenにsizeofでclient_addrのサイズを代入・・・。

acceptに、soc, client_addrのアドレス, client_addr_lenのアドレスを渡して、client_addrに相手のIPなどの情報、戻り値accに相手のソケットファイルディスクリプタが返る・・・。
accが-1ならエラー・・・。

inet_ntoaでIPアドレスを文字列にして、client_ip_addr_strに・・・。
ntohsでポート番号もホストバイトオーダにして、client_portに・・・。
そして、その内容をprintfで出力・・・。

相手を識別するaccも、サーバソケット自身を指すsocも終了時には閉じなければいけないので、closeでどちらも閉じる・・・。

このサーバをbgstation0.comサーバ上で実行すると、

$ ./accept
soc = 3
setsockopt(SO_REUSEADDR) success.
bind success.
listen success.

ここで相手の接続待ちとなる・・・。

相手となるクライアントとして、ここでは別のターミナルでtelnetで接続してみる・・・。

ポート番号3000なので、

$ telnet bgstation0.com 3000

を実行すると、

$ telnet bgstation0.com 3000
Trying 27.120.97.162...
Connected to bgstation0.com.
Escape character is '^]'.
Connection closed by foreign host.
$

と一瞬接続するが、すぐ切断する・・・。

サーバ側はどうなっているのかというと、

$ ./accept
soc = 3
setsockopt(SO_REUSEADDR) success.
bind success.
listen success.
accept!(IPAddress = 27.120.97.162, Port = 55569)
$

acceptから抜けて、相手先のIPアドレスとポート情報を出力し、終了している・・・。
(今回は、クライアントもサーバも同じbgstation0.com上で動かしているので、IPアドレスが同じ・・・。)
なので、クライアント側のtelnetはすぐ切断され終了する・・・。

Sample/accept.c at master · bg1bgst333/Sample · GitHub