C语言实现简单的HTTP服务器:处理GET、HEAD、POST请求
#include <netinet/in.h> #include <netinet/ip.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h>
#define ECHO_PORT 9999 #define BUF_SIZE 4096
int close_socket(int sock) { if (close(sock)) { fprintf(stderr, "Failed closing socket.\n"); return 1; } return 0; }
int main(int argc, char* argv[]) { int sock, client_sock; ssize_t readret; socklen_t cli_size; struct sockaddr_in addr, cli_addr; char buf[BUF_SIZE];
fprintf(stdout, "----- Echo Server -----\n");
/* all networked programs must create a socket */
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
fprintf(stderr, "Failed creating socket.\n");
return EXIT_FAILURE;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(ECHO_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
/* servers bind sockets to ports---notify the OS they accept connections */
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)))
{
close_socket(sock);
fprintf(stderr, "Failed binding socket.\n");
return EXIT_FAILURE;
}
if (listen(sock, 5))
{
close_socket(sock);
fprintf(stderr, "Error listening on socket.\n");
return EXIT_FAILURE;
}
/* finally, loop waiting for input and then write it back */
while (1)
{
cli_size = sizeof(cli_addr);
if ((client_sock = accept(sock, (struct sockaddr *) &cli_addr,
&cli_size)) == -1)
{
close(sock);
fprintf(stderr, "Error accepting connection.\n");
return EXIT_FAILURE;
}
readret = 0;
while((readret = recv(client_sock, buf, BUF_SIZE, 0)) >= 1)
{
// 解析客户端请求消息
char* method = strtok(buf, " ");
char* path = strtok(NULL, " ");
char* http_version = strtok(NULL, "\r\n");
char* header = strtok(NULL, "\r\n");
// 判断请求方法并进行不同处理
if (strcmp(method, "GET") == 0 || strcmp(method, "HEAD") == 0 || strcmp(method, "POST") == 0)
{
// Echo回去
char response[BUF_SIZE];
sprintf(response, "%s %s\r\n\r\n", http_version, buf);
if (send(client_sock, response, strlen(response), 0) != strlen(response))
{
close_socket(client_sock);
close_socket(sock);
fprintf(stderr, "Error sending to client.\n");
return EXIT_FAILURE;
}
}
else if (strcmp(method, "PUT") == 0 || strcmp(method, "DELETE") == 0 || strcmp(method, "OPTIONS") == 0)
{
// 返回501 Not Implemented
char response[] = "HTTP/1.1 501 Not Implemented\r\n\r\n";
if (send(client_sock, response, strlen(response), 0) != strlen(response))
{
close_socket(client_sock);
close_socket(sock);
fprintf(stderr, "Error sending to client.\n");
return EXIT_FAILURE;
}
}
else
{
// 返回400 Bad request
char response[] = "HTTP/1.1 400 Bad request\r\n\r\n";
if (send(client_sock, response, strlen(response), 0) != strlen(response))
{
close_socket(client_sock);
close_socket(sock);
fprintf(stderr, "Error sending to client.\n");
return EXIT_FAILURE;
}
}
memset(buf, 0, BUF_SIZE);
}
if (readret == -1)
{
close_socket(client_sock);
close_socket(sock);
fprintf(stderr, "Error reading from client socket.\n");
return EXIT_FAILURE;
}
if (close_socket(client_sock))
{
close_socket(sock);
fprintf(stderr, "Error closing client socket.\n");
return EXIT_FAILURE;
}
}
close_socket(sock);
return EXIT_SUCCESS;
}
原文地址: https://www.cveoy.top/t/topic/n36X 著作权归作者所有。请勿转载和采集!