"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > C로 간단한 TCP 서버 구축

C로 간단한 TCP 서버 구축

2024-11-08에 게시됨
검색:934

Building a Simple TCP Server in C

이 블로그 게시물에서는 HTML 파일을 제공할 수 있는 C로 간단한 TCP 서버를 만드는 방법을 살펴보겠습니다. 우리는 코드를 분석하고, 그것이 어떻게 작동하는지 설명하고, 이 프로젝트를 향상시키기 위한 향후 계획에 대해 논의할 것입니다. 이는 프로세스를 지나치게 복잡하게 하지 않고 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 

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 Repository Link에서 전체 소스 코드를 찾고 프로젝트에 기여할 수 있습니다.

부담없이 피드백을 제공하고, 질문하고, 향후 개선을 위한 아이디어를 제공해주세요!


릴리스 선언문 이 글은 https://dev.to/trish_07/building-a-simple-tcp-server-in-c-2h85에서 복제되었습니다. 침해 내용이 있는 경우, [email protected]으로 연락하여 삭제하시기 바랍니다.
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3