> 백엔드 개발 > C++ > C로 간단한 TCP 서버 구축

C로 간단한 TCP 서버 구축

DDD
풀어 주다: 2024-11-04 07:16:01
원래의
835명이 탐색했습니다.

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로 웹 서버를 만드는 방법에 대한 기본 예제 역할을 하며 언어의 강력함과 단순성을 보여줍니다. 이러한 기반을 바탕으로 보다 정교한 기능을 개발하고 성능을 향상시켜 웹 콘텐츠 제공을 위한 강력한 솔루션으로 만들 수 있습니다.

GitHub: GitHub Repository Link에서 전체 소스 코드를 찾고 프로젝트에 기여할 수 있습니다.

향후 개선을 위해 자유롭게 피드백을 제공하고, 질문하고, 아이디어를 제공해주세요!


위 내용은 C로 간단한 TCP 서버 구축의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿