はじめに
こんにちは。アメリカに住みながら独学でエンジニアを目指しているTairaです。
「ネットワークはなぜつながるのか」を使用してネットワークを学習しています。
現在第2章まで進んでいて、Httpのsocketのつながり方を学習しているので整理するために記事を書きたいと思います
1. ソケットの作成
アプリケーションはまず、通信インターフェースであるソケットを作成します。Unix系システムでは、socket()
システムコールを使ってソケットを生成します。
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
AF_INET
: IPv4を使用することを示す -
SOCK_STREAM
: TCPを使用する(接続指向型) -
0
: プロトコルはデフォルト(TCP)を使用
カーネル内にソケット用のリソースが確保され、ファイルディスクリプタ(sockfd
)が返されます。
2. connectシステムコールで接続要求
次に、アプリケーションはconnect()
を呼び出し、相手サーバーのIPアドレスやポート番号をプロトコル・スタックに知らせます。
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(80); // HTTPのポート例
inet_pton(AF_INET, "192.168.1.1", &server_addr.sin_addr);
connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
connect()
により、プロトコル・スタックに相手サーバーの情報が渡され、TCP接続の確立が開始されます。
プロトコル・スタックから相手サーバーへの接続の流れ
- ソケット情報の登録: カーネル内で送信元ポート、宛先ポート、送信元IP、宛先IPなどがソケットに関連づけられます。
- TCPセグメントの生成: TCPヘッダーに制御情報(SYNビットなど)を含むセグメントが作成されます。
- IPパケットの生成と送出: TCPセグメントはIP層でIPパケットにカプセル化され、送信インターフェースを通じてネットワークに送信されます。
- ルーティングと転送: IPパケットはルータを経由して、宛先サーバーまで到達します。
- サーバー側での受信と応答: サーバーがSYNを受信し、SYN+ACKを返すことで応答します。
このように、connect()
を呼ぶことで、カーネルのプロトコル・スタックが動作し、実際にネットワークを通じて相手サーバーとの接続が開始されます。
3. 制御情報の役割
制御情報はクライアントとサーバー間の通信を管理するために必要なもので、TCPヘッダーには以下のような重要な情報が含まれています。
- 送信元ポート番号: クライアント側のポート番号を示します。
- 宛先ポート番号: サーバー側のポート番号を示します。
- シーケンス番号: 送信されるデータの順序を管理するための番号。
- ACK番号: 正しく受信したことを相手に通知するための番号。
- コントロール・ビット: SYN、ACK、FINなど通信制御のためのフラグ。
これらの情報はソケットに記録され、プロトコル・スタックの動作を適切にコントロールする役割も果たしています。
まとめ
アプリケーションからTCP/IPスタックを介してサーバーへ接続する流れは以下の通りです。
-
socket()
でソケット作成 -
connect()
でIP・ポート番号などをプロトコル・スタックに通知し、接続要求 - プロトコル・スタックがTCP/IPパケットを生成・送信し、サーバーに到達
- 接続確立後、データ通信が可能になる