«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Создание простого TCP-сервера на C

Создание простого TCP-сервера на C

Опубликовано 8 ноября 2024 г.
Просматривать:766

Building a Simple TCP Server in C

В этом сообщении блога мы рассмотрим, как создать простой TCP-сервер на C, который может обслуживать файлы HTML. Мы разберем код, объясним, как он работает, и обсудим будущие планы по улучшению этого проекта. Это отличный пример того, как можно «просто делать что-то» на C, не усложняя процесс!

Обзор проекта

Целью этого проекта является реализация базового TCP-сервера, который прослушивает клиентские соединения и обслуживает HTML-файлы по запросу. Сервер будет обрабатывать запросы клиентов, читать указанный HTML-файл и отправлять его содержимое обратно клиенту в виде ответа HTTP.

? Продолжайте общение в Твиттере(X): @trish_07

? Репозиторий GitHub: Изучите репозиторий проекта TCP Server

Структура проекта

Чтобы организовать наш код, мы структурируем проект следующим образом:

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 

int initialize_server(struct sockaddr_in* address);

#endif

src/socket_utils.c

#include "socket_utils.h"
#include 
#include 
#include 
#include 

#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)) 



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 
#include 
#include 

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] = '\0'; // Null-terminate the buffer

    fclose(file);
    return buffer;
}

3. Обработка запросов клиентов

Теперь давайте реализуем логику обработки входящих клиентских запросов.

include/request_handler.h

#ifndef REQUEST_HANDLER_H
#define REQUEST_HANDLER_H

#include 

void handle_client(int new_socket);

#endif

src/request_handler.c

#include "request_handler.h"
#include "html_server.h"
#include 
#include 
#include 

#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

404 Not Found

"; write(new_socket, not_found_response, strlen(not_found_response)); } free(html_content); close(new_socket); // Close the connection with the current client }

4. Основная логика сервера

Наконец, давайте соберем все вместе в основной файл.

src/main.c

#include 
#include 
#include 
#include 
#include 
#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)) 



Планы на будущее

В дальнейшем мы планируем реализовать несколько улучшений и функций:

  1. Поддержка многопоточности: для одновременной обработки нескольких клиентских подключений мы добавим возможности многопоточности для повышения эффективности сервера.
  2. Динамическое обслуживание контента: реализация функций для обслуживания динамического контента путем интеграции с облегченным механизмом шаблонов.
  3. Журналирование: добавьте механизм журналирования для отслеживания запросов, ошибок и производительности сервера.
  4. Функции безопасности: попробуйте добавить поддержку HTTPS и проверку ввода для повышения безопасности.
  5. Улучшенная обработка ошибок: улучшена обработка ошибок для различных сценариев, таких как файл не найден, перегрузка сервера и т. д.

Заключение

Этот простой проект TCP-сервера служит основным примером создания веб-сервера на C, демонстрируя мощь и простоту этого языка. Основываясь на этом фундаменте, мы можем разработать более сложные функции и повысить производительность, что сделает его надежным решением для обслуживания веб-контента.

Вы можете найти полный исходный код и внести свой вклад в проект на GitHub: ссылка на репозиторий GitHub.

Не стесняйтесь оставлять отзывы, задавать вопросы или высказывать свои идеи по поводу будущих улучшений!


Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/trish_07/building-a-simple-tcp-server-in-c-2h85. Если есть какие-либо нарушения, свяжитесь с [email protected], чтобы удалить их.
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3