0

最初に Java サーバーと Android クライアントの例を書きました。サーバーにログオンするクライアントを追跡したいと考えています。ソケット オブジェクトでは、各 Android クライアントは、接続元の一意のポート番号とソケット IP アドレスを持ちます。したがって、これらはクライアントを互いに識別するためのオプションです。

ランダムに選択された 2 つの Android クライアントのポート番号が同じ番号になる可能性はほとんどないため、各クライアント ソケットのポート番号を使用しないことにしました。わずかな可能性ですが可能です。

代わりに、すべてのクライアント ソケットに含まれる別の情報の文字列である IP ソケット アドレスを使用することにしました。いいアイデアですね。そんなに早くない。

使用する関数は次のとおりです。

サーバーで

   socket.getRemoteSocketAddress()

そしてクライアントで

  socket.getLocalSocketAddress()

ただし、これらの方法を使用している場合、返されるアドレスは同じではありません。

クライアントのソケット オブジェクトで getLocaSocketlAddress() を使用し、それを文字列としてサーバーに送信した場合、後でサーバーのソケット接続で getRemoteSocketAddress() を使用して、受信したアドレスと同じかどうかを確認する必要があります。クライアントを文字列として。これは、どのクライアントからメッセージを受信したかを識別するために行われます。2 つのアドレスは、想定どおりに一致しません。

例: クライアントは、クライアントgetLocalSocketAddress()のソケット オブジェクトを呼び出してソケット アドレスを取得します -------> アドレスをメッセージ内の文字列としてサーバーに送信します ---> サーバーはメッセージを取得getRemoteSocketAddress()し、ソケットを呼び出して、送信するクライアントのみを選択しますにメッセージを返します。他のすべてのクライアントではありません。

サーバーは、接続されているクライアントのすべてのソケットを ArrayList に格納します。

getLocalSocketAddress()クライアント側のソケットで使用すると、たとえば XXX.XXX.11.17 が返されgetRemoteSocketAddress()サーバー側のソケットで使用するとXXX.XXX.0.13が返されます。これはめちゃくちゃですが、使用するとポート番号情報が完全に一致しますgetLocalPort()クライアントとgetPort()サーバーで。

したがって、メッセージを送信するクライアントを確実に識別する方法として、クライアントのポート番号を使用できる可能性があります。

メソッドの何が問題なのgetLocalSocketAddress()か、それとも壊れているのか? どのクライアントがサーバーに接続したかを識別する別の方法はありますか?

サーバー側では、Java Swing デスクトップ アプリ

  // desktop connected to the internet by eathernet cable

  socket = serversocket.accept();

    System.out.println("SOCKET ADDRESS: "
    + socket.getRemoteSocketAddress().toString());

クライアント側で、

   // Android tablet connected to internet by wifi

   public void run() {

       socket = new Socket(InetAddress.getByName(serverIP), 6789);
       socketAddress = (socket.getLocalSocketAddress().toString());

   Log.i(TAG, "SOCKET ADDRESS: " + socketAddress);
4

1 に答える 1

4

IPアドレスを使用してクライアントを追跡することは、いくつかの理由から、一般的には悪い考えです。

まず、クライアントは何らかのNATを介して接続できます。この場合、サーバーから見たリモートアドレスは、クライアント側のアドレスと同じではありません。たとえば、ADSL / WiFiルーターがNATを実行するセットアップを想像してみてください。これは(ほとんどの場合)1つのパブリックIPアドレスを持ち、WiFiデバイスは10.0.0.xまたは192.168.xxプールなどの内部IPアドレスを使用します(非常に一般的なセットアップ)。

このような設定では、複数のWiFiデバイスが(サーバーの観点から)同じIPアドレス(ルーターのパブリックIP)から接続しているように見えることに注意してください。明らかな意味:クライアントのIPアドレスは一意ではなく、一意のIP/ポートペアです。正確には、TCP接続は(ローカルIP、ローカルポート、リモートIP、リモートポート)タプルによって一意に識別できます。

最後になりましたが、クライアントは別のIPアドレスから切断して再度接続できます。これは、モバイルネットワーク(実際には、IPが動的に割り当てられているすべてのネットワーク)で非常に一般的です。

あなたの質問であなたは書いた:

たとえば、クライアントは、クライアントのソケットオブジェクトでgetLocalSocketAddress()を呼び出すことによってソケットアドレスを取得します------->メッセージ内の文字列としてサーバーにアドレスを送信します----->サーバーはメッセージを取得し、ソケットでgetRemoteSocketAddress()を呼び出しますメッセージを送り返すクライアントのみを選択します。他のすべてのクライアントではありません。

メッセージを送り返すクライアントだけを選択するという意味がよくわかりません。接続されたクライアントごとに、個別のTCP接続と個別のSocketインスタンスがあります。特定のクライアントにデータを送信するには、この特定のクライアントに関連付けられたソケットを使用します。それだけです。クライアントのIP/ポートについてはまったく気にする必要はありません。実際、それはTCP/IPプロトコルスタックのタスクです。

本当に各接続デバイスを識別したい場合は、アプリケーションプロトコルでTCP/IPの上でそれを行う必要があります。接続後に一意の識別子を送信するだけです。しかし、それはまったく別の話です。

于 2013-02-28T09:58:51.237 に答える