2015-11-25 5 views
1

Я пытаюсь написать очень простой HTTP-сервер. Я хочу разделить сервер и службу на два отдельных исполняемых файла (аналогично inetd).Простой HTTP-сервер с использованием fork и dup

Итак, у меня есть общий сервер, который разворачивает службу и выполняет ее код с помощью exec. Основной цикл выглядит следующим образом:

while(true) { 
    int client_sock; 

    if ((client_sock = accept(server_sock, (struct sockaddr *) NULL, NULL)) < 0) { 
     return -1; 
    } 

    pid_t pid = fork(); 

    if (pid == 0) { 
     close(server_sock); 
     close(0); 
     dup(client_sock); 
     close(1); 
     dup(client_sock); 
     execvp(argv[2], argv+2); 
     return -1; 
    } else if (pid < 0) { 
     assert(false); 
    } 
    close(client_sock); 
} 

служба читает на стандартного ввода и записывает на стандартный вывод и обрабатывает простые запросы HTTP. Кажется, что все работает нормально, когда я подключаюсь к своему серверу с помощью nc. nc получает и отображает ожидаемый http-ответ.

Однако, когда я подключаюсь к своему серверу с помощью веб-браузера, браузер сообщает мне, что сервер внезапно закрыл соединение (как я полагаю, ошибка ECONNRESET). Я уверен, что моя служба обработала запрос: я проверил выполнение моей службы с помощью strace, все ожидаемые «write (1, ...)» есть, и нет никаких близких (1). Еще более удивительно, что несколько раз веб-браузер получает ответ.

Что-то не так в коде? если нет, что может вызвать проблему?

ответ

2

Я думаю, проблемы кроются не в коде, который вы показали, а в программе, которую вы выполняете. Типичная проблема заключается в том, что клиент (т. Е. Ваша программа) не читает HTTP-заголовок, а просто записывает данные и заканчивает их. В этом случае дескриптор файла в браузере закрывается, пока все еще не обрабатываются данные с сервера в буфере сокета. Это заставляет серверную ОС отправлять RST-пакет, который затем вызывает ECONNRESET в браузере. Если вам повезло, браузер получил и отобрал ответ до того, как он получил RST, поэтому иногда вы увидите ошибку сброса соединения, а иногда и нет.

+0

Спасибо, ты прав. Я тестировал свою службу с другой версией сервера («nc -e»), и проблема осталась. Однако я не уверен, как решить проблему в сервисе. Случается, что клиент не закрывает соединение, поэтому, если я пытаюсь читать больше байтов, мой «прочитанный» вызов блокируется, так как клиент больше не отправляет данные ... – Nemo

+0

Хорошо, я нашел проблему. Благодарю. – Nemo