1

こんにちは、単純なパターンを使用しているため、この問題に腹を立てています。OK、サーバーソケットとすでに接続されているソケットで epoll_wait を使用する無限の while があります。新しいソケットが接続要求を送信した場合、すべて問題ありませんでした。私の問題は、接続されたソケット (現在、390k パケットを送信する 1 つのソケットを使用しているだけです) がデータを送信するときです: EPOLLONESHOT を使用するか EPOLLET を使用するかは問題ではありません。 )、epoll_wait は常に間違ったバッファで再び起動します! 私のサーバーはスレッドプールで動作しますが、現在はすべての作業を行う 1 つのスレッドのみです (テストを簡素化するため):

while (TRUE) {
        int num = epoll_wait(efd, events, MAX_EVENTS, -1);
        for (int i = 0; i < num; i++) { // ciclo epoll()
            if (events[i].events & EPOLLERR || events[i].events & EPOLLHUP || !(events[i].events & EPOLLIN)) {
                fprintf (stderr, "epoll error on socket: closed\n");
                s = epoll_ctl(efd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
            }
            else if (events[i].data.fd == serverSocket) { 
                while (TRUE) {
                    newInfoClient = server->m_bgServer->AcceptClient(&newSocketClient);
                    if (newInfoClient == NULL) { // nessun client
                        break;
                    }
                    else { 
                            printf("\nSocket accettato: %d", newSocketClient);
                            s = CSocket::MakeNonBlocking(newSocketClient);
                            if (s == -1)
                                abort();
                            event.data.fd = newSocketClient;
                            event.events = EPOLLIN | EPOLLET;
                            s = epoll_ctl(efd, EPOLL_CTL_ADD, newSocketClient, &event);
                            if (s == -1) {
                                abort();
                            }
                } 
            }
            else { 
                AbstractTcpServerGame::DownloadTcpRequest(client);
            }
        }
    }

一部のチェックやその他の内部コードを省略しました。AbstractTcpServerGame::DownloadTcpRequest(...) この関数は、ループ内の recv であり、自分のヘッダーをレスキューし、バッファー本体を取得し、ループ外の空のバッファーを確認するためだけに、-1 を返す単純な recv() を呼び出します (errno=EAGAIN またはEWOULDBLOCK)。この後、EPOLLONESHOT の場合に DownloadTcpRequest() で epoll_ctr() を使用してソケットをリアームすると、epoll_wait() が返されると、同じソケットで再び起動します!! これは私の実行ログです:

New socket (6) request (errno 11)  <--- when epoll_wait() emits EPOLLIN on socket 6
Download of 18 bytes (socket 6) <-- inside AbstractTcpServerGame::DownloadTcpRequest()
Download of 380k (socket 6) <-- another recv() loop to rescue body request
------------------- empty buffer on socket 6 ----------- <-- dummy recv to show empty buffer
New socket (6) request (errno 11)  
Download of 18 bytes (socket 6) 
Download of -1556256155 (socket 6) 
Error on socket 6 (bad::alloc exception)

クライアントは 398k (18 ヘッダー + ボディ) を送信し、すべてのデータは上記のように正しく受信されますが、ソケットをリーミングするか、EPOLLET を使用すると、epoll_wait() は別のリクエストを生成し、それらがどこで取得されたのかわかりません。

4

0 に答える 0