Двунаправленная связь GWAN с использованием веб-сокетов

Решено

Мое решение проблемы чтения состояло в том, чтобы переместить код в обработчик и использовать состояние 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;

person griffin    schedule 12.05.2013    source источник


Ответы (3)


G-WAN Servlets явно не самый эффективный способ реализации сетевого протокола.

Поскольку websockets нарушают протокол HTTP, лучше использовать G-WAN Handler.

И G-WAN Protocol Handlers посвящен этой задаче. В этой области не хватает документации и примеров, поскольку в последнее время нам пришлось сосредоточиться на приложениях на базе G-WAN.

person Gil    schedule 14.05.2013
comment
Большое спасибо, именно этого я и опасался. Не могли бы вы просто сказать мне, как справиться с этим сценарием, когда читать больше + иметь возможность писать в клиентское соединение, когда это необходимо, например. получить дескриптор клиентского сокета gwans, чтобы я мог хранить его в постоянном обработчике или kv и передавать на него данные от другого клиента (= сервлет/обработчик)? Я бы с радостью принял это как ответ, если бы вы могли добавить немного этой информации. Как всегда большое спасибо! - person griffin; 14.05.2013
comment
Не могу отредактировать свой предыдущий комментарий, но теперь он работает с помощью обработчиков. Огромное спасибо за помощь! - person griffin; 14.05.2013
comment
@griffin Не могли бы вы опубликовать свое решение? - person Nagi; 14.05.2013

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

Кроме того, я также задавался вопросом о способе оплаты, и я уверен, что он будет использовать PayPal или какой-либо другой платежный шлюз, где платежи будут автоматически конвертироваться из вашей собственной валюты в швейцарские франки. Если это прямой авторизационный продавец кредитной карты, может взиматься комиссия за обмен от вашей кредитной карты, как правило, 3%.

person Mike    schedule 12.05.2013
comment
Скопируйте и вставьте полученный код. Но важные вещи все еще находятся в тексте (если вы думаете, что это поможет, я также могу добавить различные вызовы wake_up и т. д., но я бы предпочел, чтобы все было как можно короче, поэтому я попытался обойтись без добавления всего кода в начале, и просто записал, с чем у меня проблемы) - person griffin; 12.05.2013

Как насчет использования этой библиотеки? https://github.com/payden/libwebsock вместо того, чтобы пытаться переписать полную реализацию веб-сокета?

person solisoft    schedule 13.05.2013
comment
Проблема не в самом коде websocket, это довольно просто и понятно (поэтому я не хочу возиться с другой библиотекой). Проблема в том, что... я не могу понять, как читать больше данных от клиента из сервлета. - person griffin; 13.05.2013