C - вывод printf зависит от последующего кода

Предисловие: я просто использую C, так что простите за мою некомпетентность. Причина этой проблемы, вероятно, основная.

Проблема: я пытаюсь прочитать файл и передать его через HTTP через сокет. По какой-то причине результат printf ранее прочитанного файла зависит от того, какая часть последующего кода включена.

Вот мой код.

#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#include <netinet/in.h>


int main()
{

    // open a file to serve
    FILE *file;
    file = fopen("index.html", "r");
    if (file == NULL)
    {
        printf("Failed to open file.");
        exit(EXIT_FAILURE);
    }

    // Get file content
    char file_content[1024];
    if (fgets(file_content, 1024, file) != NULL)
    {

        fclose(file);

        // Add header to file content
        char http_header[2048] = "HTTP/1.1 200 OK\r\n\n";    
        strncat(http_header, file_content, 1028);

        // This output varies depending on inclusion of proceeding code.
        printf("%s", http_header);

        // create a socket
        int server_socket;
        server_socket = socket(AF_INET, SOCK_STREAM, 0);        

        // define the address
        struct sockaddr_in server_address;
        server_address.sin_family = AF_INET;
        server_address.sin_port = htons(8001);
        server_address.sin_addr.s_addr = INADDR_ANY;

        bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address));        
        listen(server_socket, 1);

        int client_socket;        
        while (1)
        {
            client_socket = accept(server_socket, NULL, NULL);
            send(client_socket, http_header, sizeof(http_header), 0);
            close(client_socket);
        }
        return 0;
    }

}

Если я закомментирую все, что находится за оператором printf, я получу ожидаемый результат ..

HTTP/1.1 200 OK

<html><body>Hi</body></html>

Но если я запускаю весь код, я получаю это ...

HTTP/1.1 200 OK

Если я смогу хоть немного улучшить свой вопрос, дайте мне знать, как это сделать. Спасибо.


person Dylan Landry    schedule 05.01.2018    source источник
comment
O / T переместить fclose(file); и return 0; за пределы проверки if(fgets(..)). Эти вещи должны происходить независимо от того, возвращает fgets NULL или нет.   -  person yano    schedule 05.01.2018
comment
Я подозреваю, что содержимое вашего файла не включает завершающий символ \n, и ваша программа не завершается из-за бесконечного цикла, поэтому выходной буфер никогда не сбрасывается. Либо выйдите из бесконечного цикла, либо добавьте в вывод завершающий символ новой строки.   -  person Mark Benningfield    schedule 05.01.2018
comment
... или попробуйте fflush(stdout); после printf. printf буферизуется по строкам, fflush(stdout); будет очищать вручную stdout.   -  person yano    schedule 05.01.2018
comment
Ваша строка "HTTP/1.1 200 OK\r\n\n" должна быть "HTTP/1.1 200 OK\r\n\r\n" - каждая строка должна заканчиваться на \r\n. Однако вряд ли это будет вашей непосредственной проблемой.   -  person Jonathan Leffler    schedule 05.01.2018
comment
Заголовок должен быть сгенерирован до цикла; содержимое файла должно повторяться внутри цикла. Код прослушивания / приема размещен странно; Разве это не должно быть вне цикла, и вы отправляете файл только при получении соединения?   -  person Jonathan Leffler    schedule 05.01.2018


Ответы (1)


Марк Беннингфилд и Яно помогли мне разобраться в проблеме, большое спасибо вам обоим.

Когда вы выполняете printf(), вместо строки, идущей непосредственно в окно терминала, каждая строка переходит в буфер.

Каждая строка в буфере должна быть очищена, чтобы она отображалась в терминале. Буфер может быть автоматически очищен с помощью эти события

Строки, заканчивающиеся на \n, автоматически сбрасываются, поэтому первая строка HTTP/1.1 200 OK \r\n\n отображается нормально. Вторая строка <html><body>hi</body></html> не заканчивается на \n и не запускает какие-либо другие события автоматической очистки, поэтому она не отображается.

Обычно это не проблема, потому что, когда программа завершается, буфер автоматически очищается, и все строки, которые вошли в буфер через printf, отображаются в терминале. Поскольку моя программа внизу входит в бесконечный цикл while, программа никогда не завершается, и буфер никогда не сбрасывается.

Вызов fflush(stdout) после printf вызывает запись всего буфера stdout.

Подробнее о fflush

person Dylan Landry    schedule 05.01.2018
comment
Обратите внимание, что настройки буферизации строк могут отличаться в зависимости от реализации, вы просто описываете, как ваша работает по умолчанию. - person M.M; 05.01.2018
comment
Строки, заканчивающиеся на \ n, автоматически сбрасываются - ›Не совсем. Это зависит от Каковы правила автоматической очистки буфера stdout в C? - person chux - Reinstate Monica; 05.01.2018