HTTPサーバがレスポンスを返さない

投稿者: Anonymous

Cで書いたHTTPサーバーがレスポンスを返しません
何が原因なのでしょうか?

原因として考えられるのは、recvは何もデータが来なければブロックするようなので、そこで動作が止まってしまい、サーバーがデータを送信できなくなっているのでしょうか?

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <inttypes.h>
#include <string.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    int64_t MSG_BUF_SIZE = 4000;

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        perror("Socket creation error");
    }
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(3211);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("Bind Error");
        return EXIT_FAILURE;
    }

    if (listen(sock, 11) != 0) {
        perror("Listen Error");
        return EXIT_FAILURE;
    }

    char send_message_buf[4096];
    memset(send_message_buf, 0, sizeof(send_message_buf));
    snprintf(send_message_buf, sizeof(send_message_buf), "HTTP/1.0 200 OKrn"
     "Content-Length: 20rn"
     "Content-Type: text/htmlrn"
     "rn"
     "HELLOrn");

    while (true) {
        struct sockaddr_in client;
        memset(&client, 0, sizeof(client));
        int accept_sock = accept(sock, (struct sockaddr *)&client, (socklen_t *)&client);
        if (accept_sock == -1) {
            perror("Accept Error");
            return EXIT_FAILURE;
        }
        char read_buf[3000];
        size_t read_length = 0;
        char *msg_buf = calloc(MSG_BUF_SIZE, sizeof(char));
        ssize_t r;
        memset(read_buf, 0, sizeof(read_buf));
        while ((r = recv(accept_sock, read_buf, sizeof(read_buf), 0)) > 0) { // ここでブロックしている?
            printf("r = %zdn", r);
            if (read_length + r > MSG_BUF_SIZE - 1) {
                MSG_BUF_SIZE *= 2;
                msg_buf = realloc(msg_buf, (MSG_BUF_SIZE + 1) * sizeof(char));
            }
            memmove(msg_buf + read_length, read_buf, r);
            read_length += r;
        }

        if (r == 0) {
            msg_buf = strcat(msg_buf, "");
            printf("%sn", msg_buf);
        }
        else if(r == -1) {
            perror("recv Error");
            return EXIT_FAILURE;
        }

        free(msg_buf);
        if (send(accept_sock, send_message_buf, strlen(send_message_buf), 0) == -1) {
            perror("Send Error");
        }
    }
}

解決

HTTPはバージョン1.1よりPersistent Connectionsがデフォルトとなっています。そこでHTTP/1.1に対応したWebブラウザーではブラウザー側からコネクションを切断することはありません。そのためサーバー側の

while ((r = recv(accept_sock, read_buf, sizeof(read_buf), 0)) > 0) { // ここでブロックしている?

が完了することはありません。読み取れたところまでで中断し、リクエストヘッダーを解析する処理に移る必要があります。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *