C言語

【C言語】第9章第7回:ネットワークプログラミング入門

ネットワークプログラミングは、異なるシステム間でデータを交換するための重要な技術です。本記事では、C言語でのネットワークプログラミングの基礎を学びます。

0. 記事の概要

この記事を読むメリット

  • ネットワーク通信の基礎理解:ソケットプログラミングを学ぶことで、簡単なクライアント・サーバーアプリケーションを構築できるようになります。
  • 実践的なスキル:C言語を使用してネットワーク通信の基本操作を理解します。
  • 応用力の向上:インターネットベースのアプリケーションを開発する基礎を築きます。

この記事で学べること

  • ネットワークプログラミングの基本概念
  • ソケットの基本操作
  • 簡単なクライアント・サーバープログラムの作成

1. ネットワークプログラミングの基本

1.1 ネットワークプログラミングとは?

ネットワークプログラミングとは、プログラムがネットワークを通じてデータを送受信するための手法を指します。これにより、異なるコンピュータ間での通信が可能になります。

1.2 ソケットの基本概念

ソケットは、ネットワーク通信を行うためのエンドポイントを提供します。ソケットは、通信のために使用するIPアドレスとポート番号で定義されます。

1.3 ソケット通信の種類

  • TCP(Transmission Control Protocol):信頼性のある接続指向通信
  • UDP(User Datagram Protocol):軽量で信頼性の低い接続レス通信

2. ソケットプログラミングの実装

2.1 サーバープログラムの実装

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    char buffer[1024] = {0};

    // ソケットの作成
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == 0) {
        perror("Socket failed");
        exit(EXIT_FAILURE);
    }

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(8080);

    // ソケットをバインド
    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind failed");
        exit(EXIT_FAILURE);
    }

    // 接続の待機
    if (listen(server_fd, 3) < 0) {
        perror("Listen failed");
        exit(EXIT_FAILURE);
    }

    int addrlen = sizeof(client_addr);
    printf("Waiting for connections...\n");

    // クライアントの接続を受け入れる
    client_fd = accept(server_fd, (struct sockaddr*)&client_addr, (socklen_t*)&addrlen);
    if (client_fd < 0) {
        perror("Accept failed");
        exit(EXIT_FAILURE);
    }

    // メッセージを受信
    read(client_fd, buffer, 1024);
    printf("Message from client: %s\n", buffer);

    // メッセージを送信
    send(client_fd, "Hello from server", strlen("Hello from server"), 0);

    // ソケットを閉じる
    close(client_fd);
    close(server_fd);

    return 0;
}
動作解説
  1. ソケットの作成:`socket`関数を使用してサーバーソケットを作成します。
  2. バインド:ソケットを特定のIPアドレスとポートに関連付けます。
  3. 接続待機:`listen`関数でクライアント接続を待機します。
  4. メッセージ交換:クライアントからのメッセージを受信し、応答を送信します。

2.2 クライアントプログラムの実装

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

int main() {
    int client_fd;
    struct sockaddr_in server_addr;
    char buffer[1024] = {0};

    // ソケットの作成
    client_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (client_fd < 0) {
        perror("Socket failed");
        exit(EXIT_FAILURE);
    }

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    // サーバーに接続
    if (connect(client_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("Connection failed");
        exit(EXIT_FAILURE);
    }

    // メッセージを送信
    send(client_fd, "Hello from client", strlen("Hello from client"), 0);

    // メッセージを受信
    read(client_fd, buffer, 1024);
    printf("Message from server: %s\n", buffer);

    // ソケットを閉じる
    close(client_fd);

    return 0;
}
動作解説
  1. ソケットの作成:クライアントソケットを作成します。
  2. サーバーに接続:`connect`関数でサーバーに接続します。
  3. メッセージ交換:サーバーにメッセージを送信し、応答を受信します。

3. 練習問題

以下の課題に挑戦して、ネットワークプログラミングの理解を深めましょう。

  1. クライアントから送信されたメッセージをすべて大文字に変換して返すサーバーを作成してください。
  2. 複数のクライアントを同時に接続できるサーバーを作成してください。
  3. UDPソケットを使用してメッセージを送受信するプログラムを実装してください。

4. 練習問題の解答と解説

問1の解答

#include <stdio.h>
#include <ctype.h>
#include <string.h>

void toUpperCase(char* str) {
    for (int i = 0; str[i]; i++) {
        str[i] = toupper(str[i]);
    }
}

この関数は、文字列を大文字に変換します。サーバープログラムで使用してみてください。

5. まとめ

本記事では、ネットワークプログラミングの基本概念とC言語での実装について学びました。次回は、より高度なネットワーク通信の技術について掘り下げます。