ネットワーク越しにデータをやり取りするプログラムをC言語で作る。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> // close() #include <arpa/inet.h> // inet_addr(), htons() #include <netdb.h> // gethostbyname() #include <sys/socket.h> // socket(), connect(), send(), recv()
winsock2.h を使います。#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <netdb.h> #include <sys/socket.h> #define BUF_SIZE 4096 int main(void) { const char *host = "example.com"; int port = 80; // ===== 1. ホスト名をIPアドレスに解決 ===== struct hostent *server = gethostbyname(host); if (server == NULL) { fprintf(stderr, "ホスト名の解決に失敗\n"); return 1; } // ===== 2. ソケットを作成 ===== int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket"); return 1; } // ===== 3. 接続先の情報を設定 ===== struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); // ポート番号(ネットワークバイトオーダー) memcpy(&addr.sin_addr.s_addr, server->h_addr, server->h_length); // ===== 4. サーバーに接続 ===== if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("connect"); close(sockfd); return 1; } printf("接続成功: %s:%d\n\n", host, port); // ===== 5. HTTPリクエストを送信 ===== char request[BUF_SIZE]; snprintf(request, BUF_SIZE, "GET / HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", host); send(sockfd, request, strlen(request), 0); // ===== 6. レスポンスを受信して表示 ===== char buf[BUF_SIZE]; int n; while ((n = recv(sockfd, buf, BUF_SIZE - 1, 0)) > 0) { buf[n] = '\0'; printf("%s", buf); } // ===== 7. 切断 ===== close(sockfd); printf("\n\n接続を閉じました\n"); return 0; }
| 関数 | 役割 | 引数 | 戻り値 |
|---|---|---|---|
socket() | ソケットを作成 | AF_INET, SOCK_STREAM, 0 | ソケット記述子(int) |
gethostbyname() | ホスト名→IPアドレス | "example.com" | hostent構造体へのポインタ |
connect() | サーバーに接続 | sockfd, addr, addrlen | 0=成功, -1=失敗 |
send() | データを送信 | sockfd, buf, len, flags | 送信バイト数 |
recv() | データを受信 | sockfd, buf, len, flags | 受信バイト数(0=切断) |
close() | ソケットを閉じる | sockfd | 0=成功 |
htons() | ポート番号をネットワークバイトオーダーに変換 | ポート番号 | 変換後のポート番号 |
struct sockaddr_in { short sin_family; // アドレスファミリ (AF_INET) unsigned short sin_port; // ポート番号 (htons()で変換) struct in_addr sin_addr; // IPアドレス char sin_zero[8]; // パディング };
int connect_to_server(const char *host, int port) 関数として切り出し、ソケット記述子を返すようにせよ。エラー時は -1 を返す。\r\n を自動付与する send_line と、\r\n まで読み取る recv_line。./http_client example.com 80 のように、ホスト名とポートをコマンドライン引数で渡せるようにせよ。argc/argvの講座を参照。