TCP通信プログラム書きました
某お題のため,TCPによるデータ通信プログラムをコーディング中。今後のため,今回得た経験と知恵・技量を要約しておく。
1.TCP通信プログラム手順
<サーバー側>
- sock_id = socket(AF_INET, SOCK_STREAM,0) としてソケット作成
- sockaddr_in 型構造体 (socket作成時に,AF_INETを指定した場合に,アドレスを指定する構造体らしい)の必要なパラメータにデータをセットし,ソケットを通信に使うための準備(bind関数の実行)をする。サーバーの場合,sin_addr.s_addr にはサーバー自身のIPアドレスを入れるらしいのだが,このフィールドを INADDR_ANY とすると,サーバーが有している全てのIPアドレスを指定したのと同じことになる!らしい。これにより,サーバーとネットワーク的につながっている任意のクライアントがサーバープログラムのソケットに接続可能となる。
- listen(sock_id, MAX_CONNECTIONS) して,クライアントからの接続要求到着を待つ。(MAX_CONNECTIONSはそのサーバープログラムが受け入れられる最大並列接続数)
- sock_child = accept(sock_id, ...) により接続要求受け入れ。このとき,要求してきたクライアントと接続するためのソケットが自動生成されるので,このクライアントとの通信には自動生成された方のソケット(sock_child)を利用。
- sock_childを read したり write したりして,データ通信。read の返り値について
0…相手のソケットがcloseされているものと思われる状況。こちらも対応するsocketをクローズして,後片付けなり再生なりの処理を行う。
-1...エラー発生。このとき,errno にエラー番号が格納されているので,#include <errno.h> をインクルードし,strerror(errno)を printf (%s) すれば,エラーの正体が分かり,何が起こっているか理解するのにとても役立ちます! - 全て終わったら,sock_child と sock_id を close して終了
<クライアント編>
- サーバー編1.と同様にして AF_INETでSOCK_STREAMタイプのソケットを作成。
- サーバー編2.と同様,sockaddr_in構造体のメンバーに必要なサーバーとの通信用パラメータをセット.sin_addr.s_addr は接続相手のサーバーのIPアドレスとする。
- connect() 関数を利用して,手順1.で利用したソケットを利用してサーバーにコネクションをリクエスト。(許可が出なければ待ち状態になると思われ)
- 無事許可が出たら,socket を read/write してデータをやり取りする。
- 終わったらソケットをクローズして終了。