Rumah >pembangunan bahagian belakang >C++ >Membina Pelayan TCP Mudah dalam C

Membina Pelayan TCP Mudah dalam C

DDD
DDDasal
2024-11-04 07:16:01813semak imbas

Building a Simple TCP Server in C

Dalam catatan blog ini, kami akan meneroka cara mencipta pelayan TCP mudah dalam C yang boleh menyediakan fail HTML. Kami akan memecahkan kod, menerangkan cara ia berfungsi dan membincangkan rancangan masa depan untuk mempertingkatkan projek ini. Ini adalah contoh terbaik bagaimana anda boleh "melakukan sesuatu" dalam C tanpa merumitkan proses!

Gambaran Keseluruhan Projek

Matlamat projek ini adalah untuk melaksanakan pelayan TCP asas yang mendengar sambungan klien dan menyediakan fail HTML atas permintaan. Pelayan akan mengendalikan permintaan pelanggan, membaca fail HTML yang ditentukan dan menghantar semula kandungan kepada klien sebagai respons HTTP.

? Teruskan perbualan di Twitter(X): @trish_07

? Repositori GitHub: Terokai Repositori Projek Pelayan TCP

Struktur Projek

Untuk menyusun kod kami, kami akan menstruktur projek seperti berikut:

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

Pecahan Kod

1. Utiliti Soket

Mula-mula, mari buat fail utiliti untuk mengendalikan permulaan soket. Ini akan memastikan kod pelayan utama kami kekal bersih dan fokus.

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. Fungsi Penyajian HTML

Seterusnya, kami akan mencipta fungsi untuk menyediakan fail HTML. Fungsi ini akan membaca kandungan fail HTML dan mengembalikannya kepada pemanggil.

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. Mengendalikan Permintaan Pelanggan

Sekarang, mari kita laksanakan logik untuk mengendalikan permintaan pelanggan yang masuk.

serta/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. Logik Pelayan Utama

Akhir sekali, mari kita susun semuanya dalam fail utama.

src/main.c

Rancangan Masa Depan

Melangkah ke hadapan, terdapat beberapa peningkatan dan ciri yang kami merancang untuk melaksanakan:

  1. Sokongan Berbilang Threading: Untuk mengendalikan berbilang sambungan pelanggan serentak, kami akan memperkenalkan keupayaan threading untuk meningkatkan kecekapan pelayan.
  2. Penyajian Kandungan Dinamik: Laksanakan fungsi untuk menyampaikan kandungan dinamik dengan menyepadukan dengan enjin templat yang ringan.
  3. Pengelogan: Tambahkan mekanisme pengelogan untuk menjejak permintaan, ralat dan prestasi pelayan.
  4. Ciri Keselamatan: Terokai penambahan sokongan HTTPS dan pengesahan input untuk meningkatkan keselamatan.
  5. Pengendalian Ralat yang Dipertingkat: Laksanakan pengendalian ralat yang lebih baik untuk pelbagai senario, seperti fail tidak ditemui, beban pelayan yang berlebihan, dsb.

Kesimpulan

Projek pelayan TCP mudah ini berfungsi sebagai contoh asas cara mencipta pelayan web dalam C, menunjukkan kuasa dan kesederhanaan bahasa. Dengan membina asas ini, kami boleh membangunkan ciri yang lebih canggih dan meningkatkan prestasi, menjadikannya penyelesaian yang mantap untuk menyajikan kandungan web.

Anda boleh mencari kod sumber lengkap dan menyumbang kepada projek di GitHub: Pautan Repositori GitHub.

Jangan ragu untuk memberikan maklum balas, bertanya soalan atau menyumbang idea anda untuk penambahbaikan pada masa hadapan!


Atas ialah kandungan terperinci Membina Pelayan TCP Mudah dalam C. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn