解決済み
読み取りの問題に対する私の解決策は、コードをハンドラーに移動し、HDL_AFTER_READ 状態を使用して websocket 接続を処理することでした。ハンドシェイクをリプライバッファに入れた後、2 を返して送信します。さらに、トラフィックがない場合に接続が閉じられるまでの時間を指定するため、KALIVE_TMO を変更することもできます。後で接続を特定できないように見えるため (US_REQUEST_DATA はここでは機能しません)、websocket の全体をまだ完成させていませんが、それは別のトピックであり、ここでのみ言及するので、人々は私がなぜそうしているのかを知ることができます(まだ)コードを更新していません。
-- 元の質問:
私は現在、websocket を GWAN ( http://gwan.com/ ) 4.3.14 で動作させようとしているところです。これまでのところ、firefox/chrome との接続ハンドシェイクを通過しましたが、その後、数秒後に接続が閉じます。
おそらくサーバーから PONG が欠落している可能性がありますが、私の問題は、サーブレットからクライアントからさらにデータを読み取る方法がわからないことです。ハンドラーからそれを行うことが可能であるように思われることがわかりました(少なくともマニュアルによると、これは間違っている/時代遅れであることが数回わかりました)が、いくつかの可能性もあるようです私が好むサーブレットを使用しています。
これまでに私は試しました: - get_env(argv, HTTP_HEADERS) の file_fd に WK_FD を使用した wake_up ; wake_up は、私が何をしても機能しないようです (1000 から 100000 までの値で WK_MS を使用してみましたが、違いはありません - RC_NOHEADERS + RC_STREAMING を返した直後にサーブレットが再度呼び出されました) - recv on get_env(argv, CLIENT_SOCKET) ; ここで recv は、私が操作しているもの (値 0 の int) はソケットではないことを教えてくれます (過去に CLIENT_SOCKET を動作させたことがありません。そこで何か間違ったことをしているに違いありませんか?) - 単純な sleep(1) (最大20) 呼び出し - クライアントの Wireshark + サーバーの tcpdump によって、クライアントからサーバーにデータが転送されていることがわかったとしても、READ_XBUF にはその後新しいデータがありません。
また、過去に「クライアントからさらにデータを読み取る」ために1を返すさまざまなハンドラー状態を使用してみました(いくつかのバージョンより前のバージョンなので、これはすでに修正されている可能性があります-しかし、前述のように、サーブレットを使用したソリューションをお勧めします)。これは、単純な ajax ポスト リクエストでも機能しませんでした (ほとんどのブラウザは、ポストを使用するときに 2 番目の tcp パケットでポスト データを送信するため、最初は gwan でペイロードを取得しません)。
PS: 余談ですが (ここですべての gwan 関連の質問ではないにしても、Gil がほとんどの質問に答えていることは知っています)、私は GWAN Web サイトで趣味のサポート契約にサインアップしたいと思っていましたが、方法がわかりませんでした。最初の価格表(これを書いている時点ではユーロでは利用できません)を乗り越えるためです。
これを解決するのに役立つあらゆる種類のコードを喜んで提供します。
どうぞよろしくお願いいたします。
編集:メイン関数のコード(終了コードが間違っていることはわかっているので、ここでの質問の理由ではないので、今のところ無視してください)
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;