Nesta postagem do blog, exploraremos como criar um servidor TCP simples em C que pode servir arquivos HTML. Detalharemos o código, explicaremos como ele funciona e discutiremos planos futuros para aprimorar este projeto. Este é um excelente exemplo de como você pode "simplesmente fazer coisas" em C sem complicar demais o processo!
O objetivo deste projeto é implementar um servidor TCP básico que escuta conexões de clientes e fornece arquivos HTML mediante solicitação. O servidor tratará as solicitações do cliente, lerá o arquivo HTML especificado e enviará o conteúdo de volta ao cliente como uma resposta HTTP.
Para organizar nosso código, estruturaremos o projeto da seguinte forma:
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
Primeiro, vamos criar um arquivo utilitário para lidar com a inicialização do soquete. Isso garantirá que o código do nosso servidor principal permaneça limpo e focado.
include/socket_utils.h
#ifndef SOCKET_UTILS_H #define SOCKET_UTILS_H #includeint 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. Funcionalidade de serviço HTML
A seguir, criaremos uma função para servir arquivos HTML. Esta função irá ler o conteúdo de um arquivo HTML e retorná-lo ao chamador.
include/html_server.h
#ifndef HTML_SERVER_H #define HTML_SERVER_H char* serve_html(const char* filename); #endifsrc/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. Tratamento de solicitações de clientes
Agora, vamos implementar a lógica para lidar com solicitações recebidas de clientes.
include/request_handler.h
#ifndef REQUEST_HANDLER_H #define REQUEST_HANDLER_H #includevoid 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. Lógica do Servidor Principal
Finalmente, vamos juntar tudo no arquivo principal.
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)) Planos futuros
No futuro, há vários aprimoramentos e recursos que planejamos implementar:
- Suporte multi-threading: Para lidar com múltiplas conexões de clientes simultaneamente, apresentaremos recursos de threading para melhorar a eficiência do servidor.
- Serviço de conteúdo dinâmico: implemente funcionalidade para fornecer conteúdo dinâmico integrando-o a um mecanismo de modelagem leve.
- Registro: adicione um mecanismo de registro para rastrear solicitações, erros e desempenho do servidor.
- Recursos de segurança: explore a adição de suporte HTTPS e validação de entrada para aumentar a segurança.
- Tratamento de erros aprimorado: Implemente melhor tratamento de erros para vários cenários, como arquivo não encontrado, sobrecarga do servidor, etc.
Conclusão
Este projeto simples de servidor TCP serve como um exemplo básico de como criar um servidor web em C, demonstrando o poder e a simplicidade da linguagem. Com base nesta base, podemos desenvolver recursos mais sofisticados e melhorar o desempenho, tornando-a uma solução robusta para servir conteúdo da web.
Você pode encontrar o código-fonte completo e contribuir com o projeto no GitHub: GitHub Repository Link.
Sinta-se à vontade para fornecer feedback, fazer perguntas ou contribuir com suas ideias para melhorias futuras!
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3