이 블로그 게시물에서는 HTML 파일을 제공할 수 있는 간단한 TCP 서버를 C로 만드는 방법을 살펴보겠습니다. 우리는 코드를 분석하고, 그것이 어떻게 작동하는지 설명하고, 이 프로젝트를 향상시키기 위한 향후 계획에 대해 논의할 것입니다. 이는 프로세스를 지나치게 복잡하게 하지 않고 C에서 "단순한 작업"을 수행할 수 있는 방법을 보여주는 훌륭한 예입니다!
이 프로젝트의 목표는 클라이언트 연결을 수신하고 요청 시 HTML 파일을 제공하는 기본 TCP 서버를 구현하는 것입니다. 서버는 클라이언트 요청을 처리하고 지정된 HTML 파일을 읽은 다음 콘텐츠를 HTTP 응답으로 클라이언트에 다시 보냅니다.
코드를 정리하기 위해 프로젝트를 다음과 같이 구성하겠습니다.
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
먼저 소켓 초기화를 처리하는 유틸리티 파일을 만들어 보겠습니다. 이렇게 하면 기본 서버 코드가 깔끔하고 집중된 상태로 유지됩니다.
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; }
다음으로 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; }
이제 들어오는 클라이언트 요청을 처리하는 로직을 구현해 보겠습니다.
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; }
마지막으로 모든 것을 메인 파일에 모아보겠습니다.
src/main.c
앞으로 우리는 다음과 같은 몇 가지 개선 사항과 기능을 구현할 계획입니다.
이 간단한 TCP 서버 프로젝트는 C로 웹 서버를 만드는 방법에 대한 기본 예제 역할을 하며 언어의 강력함과 단순성을 보여줍니다. 이러한 기반을 바탕으로 보다 정교한 기능을 개발하고 성능을 향상시켜 웹 콘텐츠 제공을 위한 강력한 솔루션으로 만들 수 있습니다.
GitHub: GitHub Repository Link에서 전체 소스 코드를 찾고 프로젝트에 기여할 수 있습니다.
향후 개선을 위해 자유롭게 피드백을 제공하고, 질문하고, 아이디어를 제공해주세요!
위 내용은 C로 간단한 TCP 서버 구축의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!