Решено
Мое решение проблемы чтения состояло в том, чтобы переместить код в обработчик и использовать состояние HDL_AFTER_READ для обработки подключения к веб-сокету. После помещения рукопожатия в буфер ответа верните 2, чтобы отправить его. Кроме того, вы можете изменить KALIVE_TMO, так как это определяет, через какое время соединение закрывается при отсутствии трафика. Я до сих пор не закончил работу с веб-сокетами, так как после этого я не могу идентифицировать соединение (US_REQUEST_DATA здесь не работает), но это другая тема, и я упоминаю об этом только здесь, чтобы люди знали, почему я (пока) не обновляя мой код.
-- Оригинальный вопрос:
В настоящее время я пытаюсь заставить веб-сокеты работать с GWAN (http://gwan.com) 4.3 .14. До сих пор я прошел рукопожатие соединения с firefox/chrome, но после этого соединение закрывается через несколько секунд.
У меня уже есть предположение, почему это происходит, и, вероятно, это отсутствие PONG на сервере, но теперь моя проблема заключается в том, что я не могу понять, как получить больше данных от клиента из сервлета. Я обнаружил, что это можно сделать из обработчика (по крайней мере, в соответствии с руководством, которое я несколько раз считал неправильным/устаревшим), но также есть несколько возможностей. используя сервлеты, которые я бы предпочел.
До сих пор я пробовал: - wake_up с WK_FD на file_fd get_env(argv, HTTP_HEADERS); wake_up, кажется, не работает независимо от того, что я делаю (пробовал использовать WK_MS со значениями от 1000 до 100000 без разницы - сервлет снова вызывался сразу после возврата RC_NOHEADERS + RC_STREAMING) - recv on get_env(argv, CLIENT_SOCKET) ; здесь recv говорит мне, что все, над чем я работаю (int со значением 0), не является сокетом (в прошлом CLIENT_SOCKET также никогда не работал, я должен делать что-то не так?) - простой сон (1) (до 20) вызовы - READ_XBUF не имеет новых данных после этого, даже если wireshark на клиенте + tcpdump на сервере говорит мне, что данные идут от клиента к серверу
Я также пытался использовать различные состояния обработчика, возвращающие 1 для «чтения дополнительных данных с клиента» в прошлом (некоторые версии назад, так что, возможно, это уже исправлено, но, как уже говорилось, я бы предпочел решение с сервлетами). Это не сработало даже с простым почтовым запросом ajax (большинство браузеров отправляют данные сообщения во втором пакете tcp при использовании сообщения, поэтому вы изначально не получаете полезную нагрузку с помощью gwan), так что и здесь не повезло.
PS: На заметку (поскольку я знаю, что Гил отвечает здесь на большинство, если не на все вопросы, связанные с gwan), я уже несколько раз хотел подписать контракт на поддержку любителей на веб-сайте GWAN, но я не узнал, как чтобы обойти первоначальный прайс-лист (который не доступен в евро на момент написания этой статьи).
Я с радостью предоставлю любой код, который может помочь решить эту проблему,
Большое спасибо за уделенное время.
Изменить: код основной функции (я знаю, что код завершения неправильный, поэтому пока игнорируйте его, так как это также не является причиной моего вопроса здесь)
printf("\n---------- RUN ---------\n");
xbuf_t *reply = get_reply(argv);
xbuf_t *request = (xbuf_t *)get_env(argv, READ_XBUF);
void **pdata = (void**)get_env(argv, US_REQUEST_DATA);
if (!pdata[0]) { // no request data yet, send upgrade to websocket
char *upgrade = xbuf_findstr(request, "\r\nUpgrade: websocket\r\n"); // FF only sends this ; chrome also sends "Connection: Upgrade\r\n" afterwards
if (upgrade != NULL) { // correct upgrade header found?
const char keyHeader[] ="\r\nSec-WebSocket-Key: ";
char *key = xbuf_findstr(request, (char *)keyHeader);
if (key != NULL && (key += sizeof(keyHeader) - 1) != NULL && (request->len - (u32)(key - request->ptr)) >= (u32)23) { // correct key header found? + sanity check
char websocketGUID[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // 8 + 4 + 4 + 4 + 12 = 32 + 4 bytes for '-' = 36
const char data[] = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %20B\r\n\r\n";
// 36 + 24
char keyCompose[60];
strncpy(keyCompose, key, 24);
strncpy(keyCompose + 24, websocketGUID, 36);
u8 sha[20];
sha1_t ctx;
sha1_init(&ctx);
sha1_add(&ctx, (u8 *)keyCompose, 60);
sha1_end(&ctx, sha);
xbuf_xcat(reply, (char *)data, sha);
pdata[0] = (void*)1;
printf("Init.");
return RC_NOHEADERS + RC_STREAMING; // don't build headers automatically
}
}
} else { // websocket connection here
const unsigned char websocketTerm[2] = { 0x00, 0xFF }; // websocket close = opcode 0x8
printf("Streaming!\n"); // TODO: next find way to get next user input (best would be to only wake up on user input or if we have something to send?)
char *buf = alloca(2);
buf[0] = 0; buf[1] = 0;
pdata[0]++;
if ((int)(pdata[0]) >= 20) {
xbuf_ncat(reply, (char *)websocketTerm, 2);
printf("Fin.\n");
pdata[0] = 0; // cleanup
return RC_NOHEADERS;
}
return RC_NOHEADERS + RC_STREAMING;
}
xbuf_cat(reply, "test");
return 403;