Отправка Server-Sent-Events через сокет в C

У меня есть C-приложение, которое создает данные, которые я хочу отправить на веб-сайт, используя события, отправленные сервером.

Я реализовал базовый веб-сервер на C, который отправляет Http-заголовок после получения запроса Http, а затем данные с интервалом в 1 секунду через сокет.

Я зарегистрировал свой сокет как Event-Source и передаю правильный HTTP-заголовок (согласно Firebug), но по какой-то причине eventListener не вызывается.

var source = new EventSource('http://192.168.2.113:10001/'); 

source.addEventListener('message', function(e) {
/* */
}, false); 

Я попытался отправить события из приложения php, и это сработало без проблем, так что думаю, проблема не на стороне javascript.

Когда я просто открываю http://192.168.2.113:10001/ в своем браузере, отображаются строки данных, которые я отправляю с интервалом в 1 секунду.

Я нашел только реализации sse с использованием php или cgi, которые я не хочу использовать.

Заголовок моего ответа:

HTTP/1.1 200 OK\n
Date: Fri, 05 Jul 2013 15:05:15 GMT\n
Cache-Control: no-cache\n
Connection: Keep-Alive\n
Transfer-Encoding: chunked\n
Content-Type: text/event-stream\n
\n

Данные события:

data: Testdata...\n\n

person ledo    schedule 08.07.2013    source источник
comment
Можете ли вы привести несколько примеров части кода C для отправки sse? Мне это очень интересно, и я ищу пример, с которым можно поиграть. Спасибо!   -  person Jun    schedule 31.03.2016


Ответы (2)


В кодировке chunked каждому фрагменту данных предшествует строка, описывающая размер фрагмента. Вы не показываете, что предоставляете этот размер, поэтому данные вашего события не соответствуют формату кодирования chunked.

Длина указывается в шестнадцатеричном формате, поэтому в вашем случае 18 байтов данных будут закодированы как 12 в шестнадцатеричном формате. Когда фрагментов больше нет (то есть ответ завершен), отправляется фрагмент размером 0.

Многие клиенты примут обычный символ \n в качестве надлежащего терминатора блока данных, но HTTP RFC указывает, что следует использовать \r\n. Таким образом, каждый \n в вашем заголовке должен быть изменен на \r\n. и ваши куски должны выглядеть так:

12\r\ndata: Testdata...\n\r\n

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

person jxh    schedule 08.07.2013
comment
Должен ли заголовок также включать размер? Я использую проволочную акулу, и я вижу, что она также указывает длину в начале. Кроме того, есть конечный фрагмент с нулевым размером, верно? - person Timtianyang; 31.05.2016
comment
@Timtianyang: нет необходимости в Content-Length при использовании кодировки chunked. Да, конечный фрагмент имеет размер 0, как указано в ответе. - person jxh; 31.05.2016

Каждая строка в заголовке HTTP должна завершаться с помощью \r\n.

См. rfc2616, раздел 2.2 Основные правила.

   CR             = <US-ASCII CR, carriage return (13)>
   LF             = <US-ASCII LF, linefeed (10)>

HTTP/1.1 определяет последовательность CR LF как маркер конца строки для всех элементов протокола, кроме тела объекта.

В вашем примере используется просто \n, поэтому для некоторых простых http-клиентов все заголовки могут казаться частью одной строки. Попробуйте изменить конец каждой строки, которая не является частью объекта, с помощью \r\n

person simonc    schedule 08.07.2013
comment
также после последней строки HTTP-заголовка. Он должен быть завершен \r\n 2 раза - person Denny Mathew; 08.07.2013
comment
@DennyMathew Похоже, это делается правильно (см. \n в строке после заголовка Content-Type в вопросе) - person simonc; 08.07.2013
comment
,, о к.. только что сделал утверждение только... tnx - person Denny Mathew; 08.07.2013