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!
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.
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
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; }
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
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; }
Akhir sekali, mari kita susun semuanya dalam fail utama.
src/main.c
Melangkah ke hadapan, terdapat beberapa peningkatan dan ciri yang kami merancang untuk melaksanakan:
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!