Проблемы с C, HTTP 1.1 и Socket Send

В дополнение к моему предыдущему сообщению на Создание веб-сервера на чистом C, у меня проблемы с функцией отправки. Вот два фрагмента кода:

int Send(char *message)
{
        int length, bytes_sent;
        length = strlen(message);

        bytes_sent = send(connecting_socket, message, length, 0);

        return bytes_sent;
}

Этот код отправляет void * в текущий сокет. Работает как шарм!

Теперь идет SendHTML

void SendHTML(char *Status_code, char *Content_Type, char *HTML)
{
        char *head = "\r\nHTTP/1.1 ";
        char *content_head = "\r\nContent-Type: ";
        char *server_head = "\r\nServer: PT06";
        char *length_head = "\r\nContent-Length: ";
        char *date_head = "\r\nDate: ";
        char *newline = "\r\n";
        char Content_Length[100];
        int content_length = strlen(HTML);

        sprintf(Content_Length, "%i", content_length);

        char *message = malloc((
                strlen(head) +
                strlen(content_head) +
                strlen(server_head) +
                strlen(length_head) +
                strlen(date_head) +
                strlen(newline) +
                strlen(Status_code) +
                strlen(Content_Type) +
                strlen(Content_Length) +
                content_length +
                sizeof(char)) * 2);

        if ( message != NULL )
        {
                time_t rawtime;

                time ( &rawtime );

                strcpy(message, head);

                strcat(message, Status_code);

                strcat(message, content_head);
                strcat(message, Content_Type);
                strcat(message, server_head);
                strcat(message, length_head);
                strcat(message, Content_Length);
                strcat(message, date_head);
                strcat(message, (char*)ctime(&rawtime));
                strcat(message, newline);
                strcat(message, HTML);

                Send(message);

                free(message);
        }     
}

Если бы я добавил

Send("Oh end of HTML Sending eh?");

после Send(message) и до free(message) это не отправляется в браузер?

Я подумал, что это может быть проблема HTTP 1.1, говорит ли RFC, что я могу сделать только одну отправку? Закрывает ли браузер соединение после получения первого сообщения?

Как мне решить эту проблему, чтобы я мог сделать следующее:

SendHTML("200 OK", "text/plain", "HAaaaii!!");
Send("lolwut?");

Это должно привести к тому, что браузер покажет:

HAaaaii!!lolwut?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
3 040
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Поскольку вы отправляете длину содержимого, браузер больше не будет принимать содержимое после "HAaaaii !!" и почему интерпретируете "лолвут"? как часть ответа на его следующий запрос, который, конечно же, не удастся.

Вы можете пропустить отправку длины содержимого, но это будет означать, что вы не используете keep-alive и, следовательно, не можете обрабатывать более одного запроса на одно TCP-соединение.

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

В вашей переменной head не должно быть ведущего "\r\n". Вероятно, это и вызывает проблему. Кроме того, когда вы распределяете свое сообщение, вы не резервируете достаточно места для даты и времени (26 байтов согласно документации для ctime(3)), поэтому вы почти наверняка перезаписываете свой буфер и вызываете повреждение кучи.

Если вы хотите начать отправку данных до того, как узнаете, что такое Content-Length, вы можете вместо этого использовать кодирование передачи по частям. Кодирование передачи по частям гласит: «Я собираюсь предоставлять вам кучу данных фрагментами, и я могу сказать вам, какова длина каждого фрагмента, но я не знаю, сколько фрагментов существует, пока не закончу. " Например, Google использует кодировку передачи по частям. Вот след HTTP-запроса к домашней странице Google, созданного с помощью cURL:

curl www.google.com --trace-ascii -
(Header snipped -- but no Content-Length header)

Поток данных состоит из размера блока (в шестнадцатеричном формате), за которым следует CRLF, а затем байты данных. В этом случае был только один кусок, но его легко могло быть больше. После последнего фрагмента передается размер фрагмента 0, указывающий на последний фрагмент.

Вы добавляете новую строку после каждого заголовка?

Вы, конечно, можете протестировать свое приложение с помощью telnet и посмотреть, что получится.

Нет, не обязательно иметь только одну отправку. Предположим, потоковая передача файла размером 2 ГБ. Это просто не логично.

Другие вопросы по теме