0

これは、UDP プロトコルに基づいてすべてのクライアントと通信する C++ サーバー アプリケーションです。ユーザーがクライアントからサーバーにログインすると、クライアント アプリケーションは UDP チャネルをサーバーに登録します。このチャネルは IP+Port という固定形式です。つまり、IP が変更されない場合、クライアントにログインしているユーザーがどのユーザーを登録してもかまいません。同じチャンネル。

サーバーのソケット レイヤーは、3 分間チャネルからハートビート パケットを受信しない場合、チャネルを削除するハートビート メカニズムを維持します。クライアントがダウンするまで、たとえばネットワーク ワイヤが切断されるまで、すべてが正常に機能します。以下のシーンを見てください。

    1. User-A logs into server. The Client registers channel (IP:Port) 
       to the server. Because the UDP channel is alive, so the Server 
       sets the User status of User-A as Online. 

    2. Kill the client process, and within 3 minutes(before the channel 
       timeouts in server), let User-B logs into server from the same 
       computer. Because the IP remains unchanged, so actually the client 
       registers a same (IP:PORT) pair to the server as it did when User-A
       logs in.

    3. Since the Server receives packets from (IP:PORT), so it considers
       User-A is still alive, thus setting the user status of User-A as 
       Online which is not right anymore.

上記のシナリオでは、サーバーは同じコンピューターからログに記録されたさまざまなユーザーを区別できないため、ユーザーの状態が正しくありません。この問題を解決する方法を知っている人はいますか?

4

1 に答える 1

0

クライアント アプリケーションが UDP ソケットを明示的にバインドしていない限り、任意の 2 人のユーザーのオリジン ポート番号が同一であると推測する理由はありません。通信を開始するクライアントは、多くの場合、エフェメラル ポートを同様に効果的に使用できます。エフェメラル ポートは、特定のユース ケースに対して十分にランダムである場合とそうでない場合があります。以下のコードは、インバウンド UDP データからクライアント ポートにアクセスする方法を示しています。それらが十分にランダムでない場合は、セッション cookie またはユーザー cookie をプロトコルにエンコードすることが賢明な場合があります。

#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>

int 
main() {
        /*- setup UDP socket on 8500 */
        int rc;
        int server_socket;
        struct sockaddr_in server_address;

        server_socket = socket(AF_INET, SOCK_DGRAM, 0);
        if (server_socket < 0) {
                perror("failed to init socket");
                return 1;
        }

        memset(&server_address, 0, sizeof(server_address));
        server_address.sin_family      = AF_INET;
        server_address.sin_port        = htons(8500);
        server_address.sin_addr.s_addr = inet_addr("127.0.0.1");

        rc = bind(server_socket, (struct sockaddr*) &server_address
                , sizeof(server_address));

        if (rc < 0) { 
                perror("failed to bind");
                return 2;
        }

        /* - receive from UDP socket and print out origin port - */
        char buffer[4096];
        struct sockaddr_in client_address;
        int client_address_len = sizeof(client_address);

        rc = recvfrom(server_socket
                    , buffer 
                    , sizeof(buffer)
                    , 0
                    , (struct sockaddr*) &client_address
                    , &client_address_len);

        if (rc < 0)
                return 3;

        fprintf(stderr, "%s %d\n", buffer, ntohs(client_address.sin_port));

        return 0;
}
于 2013-12-26T04:38:01.027 に答える