2

libwebsocketsCのwebsocketライブラリである for client でコーディングしています。

select()そして、他のイベントを処理しながらwebsocketを処理できるように、websocketファイル記述子を使用したいと考えています。

そして、websocket がイベントを取得した場合にのみ、websocketlibwebsocket_service();イベントを処理するために呼び出すことができます。

だから私は以下の手順を試しました。

  1. 経由で websocket を接続しますstruct libwebsocket *wsi = libwebsocket_client_connect(..) 。reture 値が NULL であるかどうか、エラーがないかどうかも確認しました。

  2. int を使用してファイル記述子を取得するfd = libwebsocket_get_socket_fd(wsi);

  3. FD_SET(fd, &readFd);select(maxFd + 1, &readFd, NULL, NULL, NULL);

しかし、接続が完了した後にサーバーがメッセージを送信するため、ウェイクアップする必要があると思いますが、ブロックされ続けます。

- -編集 - -

さらにテストした後。

接続が完了する前に select() が呼び出されるためと思われます。LWS_CALLBACK_CLIENT_ESTABLISHED を処理する前を意味します。

と の間にlibwebsocket_service()もう 1 つ入れて、を呼び出す前に処理できるようにします。libwebsocket_client_connect()select()LWS_CALLBACK_CLIENT_ESTABLISHEDselect()

そして、サーバーからメッセージを受信すると、select() で動作します。

処理後にソケットが通常開いていることを意味しますLWS_CALLBACK_CLIENT_ESTABLISHEDか?

4

2 に答える 2

2

あなたは丘の上に水を押し上げようとしています。

警告: クライアントではなく、これを行うサーバーのみを作成しました。ただし、インターフェースは非常に似ています

まず、ではなくorlibwebsocketsを使用することに基づいて記述します。も使えると思いますが、または;を使うと生活が楽になります。使用するコードを書き直すのに約 10 分かかりました。本当にを使用したい場合は、 を使用して外部ポーリングを機能させてから、 を使用するように書き直すことをお勧めします。pollppollselectselectpollppollselect()ppollselectppollselect()

次に、 を見てください。具体的には、が定義されているtest-server.c場合にコードがどのように変化するかを見てください。EXTERNAL_POLLまた、API ドキュメントのこの部分も読みたいと思います。

次の 4 つの理由はオプションであり、libwebsockets ソケットを外部ポーリング配列に統合する場合にのみ注意する必要があります。

LWS_CALLBACK_ADD_POLL_FD

libwebsocket は内部でポーリング ループを処理しますが、別のサーバーと統合する場合は、libwebsocket ソケットがポーリング配列を他のサーバーと共有する必要があります。これと他の POLL_FD 関連のコールバックを使用すると、プロトコル 0 のコールバックに専用のポーリング配列インターフェイス コードを配置できます。プロトコル 0 は、サポートする最初のプロトコルであり、通常はサービング ケースの HTTP プロトコルです。このコールバックは、fd を含むソケットをポーリング ループに追加する必要があり、len がイベント ビットマップ (POLLIN など) である場合に発生します。内部ポーリング ループ (「サービス」コールバック) を使用している場合は、これらのコールバックを無視できます。

LWS_CALLBACK_DEL_POLL_FD

このコールバックは、外部ポーリング配列からソケット記述子を削除する必要がある場合に発生します。in はソケット記述子です。内部ポーリング ループを使用している場合は、無視してかまいません。

LWS_CALLBACK_SET_MODE_POLL_FD

このコールバックは、libwebsockets が in のソケット記述子のイベントを変更したい場合に発生します。ハンドラーは、このソケット記述子の pollfd 構造体のイベント メンバーに対して OR len を実行する必要があります。内部ポーリング ループを使用している場合は、無視してかまいません。

LWS_CALLBACK_CLEAR_MODE_POLL_FD

このコールバックは、libwebsockets が in のソケット記述子のイベントを変更したい場合に発生します。ハンドラーは、このソケット記述子の pollfd 構造体のイベント メンバーに対して AND ~len を実行する必要があります。内部ポーリング ループを使用している場合は、無視してかまいません。

これが言っていること (簡単に言えば) は、libwebsockets がこれらのメソッドを使用して呼び出し、poll配列を操作するように要求するということです。

test-server.cロックに関するいくつかの複雑さを無視すると、次のように実装されていることがわかります。

    case LWS_CALLBACK_ADD_POLL_FD:

            if (count_pollfds >= max_poll_elements) {
                    lwsl_err("LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\n");
                    return 1;
            }

            fd_lookup[pa->fd] = count_pollfds;
            pollfds[count_pollfds].fd = pa->fd;
            pollfds[count_pollfds].events = pa->events;
            pollfds[count_pollfds++].revents = 0;
            break;

    case LWS_CALLBACK_DEL_POLL_FD:
            if (!--count_pollfds)
                    break;
            m = fd_lookup[pa->fd];
            /* have the last guy take up the vacant slot */
            pollfds[m] = pollfds[count_pollfds];
            fd_lookup[pollfds[count_pollfds].fd] = m;
            break;

(サーバー側で) 2 番目の 2 つのコールバックを実装する必要があるtest-server.cとは思いません。

を呼び出した後、(再び から) 次のように、独自の FD にサービスを提供pollするように要求する必要があります。libwebsocketstest-server.c

            /*
             * this represents an existing server's single poll action
             * which also includes libwebsocket sockets
             */

            n = poll(pollfds, count_pollfds, 50);
            if (n < 0)
                    continue;


            if (n)
                    for (n = 0; n < count_pollfds; n++)
                            if (pollfds[n].revents)
                                    /*
                                    * returns immediately if the fd does not
                                    * match anything under libwebsockets
                                    * control
                                    */
                                    if (libwebsocket_service_fd(context,
                                                              &pollfds[n]) < 0)
                                            goto done;

それでは、具体的な質問に戻りましょう。

だから私は以下の手順を試しました。

  1. 経由で websocket を接続しますstruct libwebsocket *wsi = libwebsocket_client_connect(..)。reture 値が NULL であるかどうか、エラーがないかどうかも確認しました。

  2. ファイル記述子を取得するint fd = libwebsocket_get_socket_fd(wsi);

  3. FD_SET(fd, &readFd);select(maxFd + 1, &readFd, NULL, NULL, NULL);

しかし、接続が完了した後にサーバーがメッセージを送信するため、ウェイクアップする必要があると思いますが、ブロックされ続けます。

selectとの間のインピーダンスの不一致は別として、pollここでの問題は次のようになります。

a) Websocket を読み取りのためにポーリングする必要があると無条件に言っている。

b) Web ソケットに書き込むデータがあると言っているわけではありません。

適切なコールバックを取得したときに、読み取り FD と書き込み FD の両方FD_SETで(およびFD_CLEAR)を実行する必要があります。あなたはそうしていません。これにより問題が発生します。

于 2014-11-28T18:04:39.700 に答える