#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)
    {
        // 解析HTTP请求消息
        char *request_line = strtok(buf, "\r\n"); // 获取请求行
        if (request_line == NULL) {
            // 消息格式错误
            if (send(client_sock, "HTTP/1.1 400 Bad request\r\n\r\n", 29, 0) != 29) {
                close_socket(client_sock);
                close_socket(sock);
                fprintf(stderr, "Error sending to client.\n");
                return EXIT_FAILURE;
            }
            break;
        }
        char *method = strtok(request_line, " "); // 获取方法
        if (method == NULL) {
            // 消息格式错误
            if (send(client_sock, "HTTP/1.1 400 Bad request\r\n\r\n", 29, 0) != 29) {
                close_socket(client_sock);
                close_socket(sock);
                fprintf(stderr, "Error sending to client.\n");
                return EXIT_FAILURE;
            }
            break;
        }
        if (strcmp(method, "GET") == 0 || strcmp(method, "HEAD") == 0 || strcmp(method, "POST") == 0) {
            // Echo回去
            if (send(client_sock, buf, readret, 0) != readret)
            {
                close_socket(client_sock);
                close_socket(sock);
                fprintf(stderr, "Error sending to client.\n");
                return EXIT_FAILURE;
            }
        } else {
            // 没有实现
            if (send(client_sock, "HTTP/1.1 501 Not Implemented\r\n\r\n", 36, 0) != 36) {
                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;

}

C语言实现简单的HTTP服务器:解析多请求行并返回响应消息

原文地址: https://www.cveoy.top/t/topic/n35L 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录