ホームページ > バックエンド開発 > C++ > C で単純な TCP サーバーを構築する

C で単純な TCP サーバーを構築する

DDD
リリース: 2024-11-04 07:16:01
オリジナル
814 人が閲覧しました

Building a Simple TCP Server in C

このブログ投稿では、HTML ファイルを提供できる単純な TCP サーバーを C で作成する方法を検討します。コードを分解し、それがどのように機能するかを説明し、このプロジェクトを強化するための将来の計画について話し合います。これは、プロセスを過度に複雑にすることなく、C で「単に処理する」方法を示す優れた例です。

プロジェクト概要

このプロジェクトの目標は、クライアント接続をリッスンし、要求に応じて HTML ファイルを提供する基本的な TCP サーバーを実装することです。サーバーはクライアントのリクエストを処理し、指定された HTML ファイルを読み取り、その内容を HTTP 応答としてクライアントに送り返します。

? Twitter(X) で会話を続けましょう: @trish_07

? GitHub リポジトリ: TCP サーバー プロジェクト リポジトリを探索する

プロジェクトの構造

コードを整理するために、プロジェクトを次のように構造化します。

tcp_server_c/
├── CMakeLists.txt             # Build configuration
├── include/
│   ├── server.h               # Main server header file
│   ├── html_serve.h           # Header for serve_html function
│   ├── request_handler.h      # Header for handle_client function
│   └── socket_utils.h         # Header for socket utility functions
├── src/
│   ├── server.c               # Main server program
│   ├── html_serve.c           # serve_html function
│   ├── request_handler.c      # handle_client function
│   └── socket_utils.c         # Utility functions for socket operations
└── README.md                  # Project documentation
ログイン後にコピー

コードの内訳

1. ソケットユーティリティ

まず、ソケットの初期化を処理するユーティリティ ファイルを作成しましょう。これにより、メインサーバーのコードがクリーンで集中した状態に保たれます。

include/socket_utils.h

#ifndef SOCKET_UTILS_H
#define SOCKET_UTILS_H

#include <arpa/inet.h>

int initialize_server(struct sockaddr_in* address);

#endif
ログイン後にコピー

src/socket_utils.c

#include "socket_utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define PORT 8080

int initialize_server(struct sockaddr_in* address) {
    int server_fd;
    int opt = 1;

    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("Socket failed!");
        return -1;
    }

    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) != 0) {
        perror("setsockopt failed");
        close(server_fd);
        return -1;
    }

    address->sin_family = AF_INET;
    address->sin_addr.s_addr = INADDR_ANY;
    address->sin_port = htons(PORT);

    if (bind(server_fd, (struct sockaddr*)address, sizeof(*address)) < 0) {
        perror("Bind failed!");
        close(server_fd);
        return -1;
    }

    if (listen(server_fd, 3) < 0) {
        perror("Listen failed!");
        close(server_fd);
        return -1;
    }

    return server_fd;
}
ログイン後にコピー

2. HTML 配信機能

次に、HTML ファイルを提供する関数を作成します。この関数は、HTML ファイルの内容を読み取り、呼び出し元に返します。

include/html_server.h

#ifndef HTML_SERVER_H
#define HTML_SERVER_H

char* serve_html(const char* filename);

#endif
ログイン後にコピー

src/html_server.c

#include "html_server.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* serve_html(const char* filename) {
    FILE* file = fopen(filename, "r");
    if (!file) {
        perror("Error opening file");
        return NULL;
    }

    fseek(file, 0, SEEK_END);
    long length = ftell(file);
    fseek(file, 0, SEEK_SET);

    char* buffer = malloc(length + 1);
    if (!buffer) {
        perror("Error allocating memory");
        fclose(file);
        return NULL;
    }

    fread(buffer, 1, length, file);
    buffer[length] = '<pre class="brush:php;toolbar:false">#ifndef REQUEST_HANDLER_H
#define REQUEST_HANDLER_H

#include <sys/socket.h>

void handle_client(int new_socket);

#endif
ログイン後にコピー
'; // Null-terminate the buffer fclose(file); return buffer; }

3. クライアントリクエストの処理

次に、受信クライアントリクエストを処理するロジックを実装しましょう。

include/request_handler.h

#include "request_handler.h"
#include "html_server.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define BUFFER_SIZE 1024

void handle_client(int new_socket) {
    char buffer[BUFFER_SIZE] = { 0 };
    read(new_socket, buffer, BUFFER_SIZE);

    // Serve the HTML file
    char* html_content = serve_html("../html/index.html");
    if (html_content) {
        write(new_socket, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n", 48);
        write(new_socket, html_content, strlen(html_content));
    } else {
        const char* not_found_response = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<h1>404 Not Found</h1>";
        write(new_socket, not_found_response, strlen(not_found_response));
    }

    free(html_content);
    close(new_socket); // Close the connection with the current client
}
ログイン後にコピー

src/request_handler.c

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

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);

    server_fd = initialize_server(&address);
    if (server_fd == -1) {
        return EXIT_FAILURE;
    }

    printf("Server listening on port: 8080\n");

    while (1) {
        if ((new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen)) < 0) {
            perror("Connection not accepted!");
            continue;
        }
        handle_client(new_socket); // Handle the client request
    }

    close(server_fd);
    return 0;
}
ログイン後にコピー

4. メインサーバーロジック

最後に、すべてをメイン ファイルにまとめましょう。

src/main.c

今後の予定

今後、いくつかの機能強化と機能の実装を予定しています。

  1. マルチスレッドのサポート: 複数のクライアント接続を同時に処理するために、サーバーの効率を向上させるスレッド機能を導入します。
  2. 動的コンテンツの提供: 軽量のテンプレート エンジンと統合することで、動的コンテンツを提供する機能を実装します。
  3. ロギング: リクエスト、エラー、サーバーのパフォーマンスを追跡するためのロギング メカニズムを追加します。
  4. セキュリティ機能: セキュリティを強化するための HTTPS サポートと入力検証の追加を検討します。
  5. エラー処理の改善: ファイルが見つからない、サーバーの過負荷など、さまざまなシナリオ向けに改善されたエラー処理を実装します。

結論

この単純な TCP サーバー プロジェクトは、C で Web サーバーを作成する方法の基本的な例として機能し、C 言語の能力とシンプルさを実証します。この基盤の上に構築することで、より洗練された機能を開発し、パフォーマンスを向上させ、Web コンテンツを提供するための堅牢なソリューションにすることができます。

完全なソース コードを見つけて、GitHub でプロジェクトに貢献できます: GitHub リポジトリ リンク。

お気軽にフィードバックを提供したり、質問したり、将来の機能強化のためのアイデアを提供してください!


以上がC で単純な TCP サーバーを構築するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート