Linux環境でのネットワーク通信を実現するためには、ソケットAPIが基本的な役割を果たします。これはTCPやUDPといったプロトコルを利用して、プロセス間でデータを送受信するためのインターフェースです。
ソケットの概念
ソケットは、ネットワーク通信を行うためのエンドポイントとして機能し、OSによって管理されるファイルディスクリプタと関連付けられます。各ソケットは「プロトコル・ローカルIP・ローカルポート・リモートIP・リモートポート」の5要素(五つ組)で一意に識別されます。
バイトオーダーの扱い
ネットワーク通信では、異なるアーキテクチャ間でもデータ解釈を統一するため、ビッグエンディアン形式(ネットワークバイトオーダー)が標準です。ホストマシンがリトルエンディアンの場合、送受信前に変換が必要です。
バイトオーダー変換関数
htonl(x):32ビット整数をホスト→ネットワーク順に変換htons(x):16ビット整数をホスト→ネットワーク順に変換ntohl(x):32ビット整数をネットワーク→ホスト順に変換ntohs(x):16ビット整数をネットワーク→ホスト順に変換
アドレス構造体
汎用構造体sockaddrは内部で使われることが多く、実際のプログラミングではIPv4専用のsockaddr_inが主流です。
struct sockaddr_in {
sa_family_t family; // アドレスファミリ(例: AF_INET)
in_port_t port; // ポート番号(ネットワークバイトオーダー)
struct in_addr addr; // IPv4アドレス(ネットワークバイトオーダー)
char padding[8]; // アラインメント用パディング
};
struct in_addr {
uint32_t s_addr;
};
ソケット生成関数
int sock = socket(AF_INET, SOCK_STREAM, 0);
第1引数:AF_INET(IPv4)、AF_INET6(IPv6)など
第2引数:SOCK_STREAM(TCP)、SOCK_DGRAM(UDP)、SOCK_RAW(生IP)など
成功時はファイルディスクリプタ、失敗時は-1を返します。
IPアドレス変換関数
#include <arpa/inet.h>
// 文字列 → バイナリ(ネットワーク順)
inet_pton(AF_INET, "192.168.1.10", &addr.sin_addr);
// バイナリ(ネットワーク順)→ 文字列
inet_ntop(AF_INET, &addr.sin_addr, buffer, sizeof(buffer));
構造体初期化の例
struct sockaddr_in endpoint;
char ip_str[INET_ADDRSTRLEN];
memset(&endpoint, 0, sizeof(endpoint));
endpoint.family = AF_INET;
endpoint.port = htons(8080);
if (inet_pton(AF_INET, "10.0.0.1", &endpoint.addr) != 1) {
perror("Invalid address");
return -1;
}
inet_ntop(AF_INET, &endpoint.addr, ip_str, sizeof(ip_str));
printf("Configured IP: %s\n", ip_str);