2

Android で Sockets を使用すると問題が発生します。私はこのトピックに慣れていないので、トレーニングとして Android フォンから別の Android フォンへの簡単なチャットを実現しようとしています。

コードを使用して ServerSocket を作成し、同じデバイスから別のソケットに接続できます (1 つのデバイスで 1 つのクライアントのみを使用する「エコー」の例は正常に動作します) 同じ Wi-Fi で 2 つの IP アドレスを使用してそれを実行しました(192.168...) しかし、3G 接続を使用してインターネット IP アドレスを使用して遠隔クライアントに接続しようとすると、一時的に失敗します。

java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out)

私がしているのは、 ServerSocket (ServerConnect.java) を作成することです:

    private ServerSocket _mainServer = null;

    private void initServer() {

        try {
                        //port I use here is arbitrary: 8081
            _mainServer = new ServerSocket(CONNECT_SOCKET_PORT);
        } catch (IOException e) {
            Log.w("ServerSocket", e.toString());
            e.printStackTrace();
        }
    }

同じクラスの別のスレッドで、クライアント接続を待機するためにこれを行います。

        while (running) {
            GuestConnect ssc = new GuestConnect(_mainServer.accept());
            ssc.setListener(this);
            ssc.startConnection();

            _clientSockets.add(ssc);

            performGuestAdded("bra!");
        }

サーバーが複数のクライアント接続を待機するようになるため、「チャットルーム」で2人以上の人をホストできます。

通信サーバー側は、ローカル クライアントのコールバックから作成され、すべてのゲストにメッセージをディスパッチします (私はまだこの部分に取り組んでいますが、実際にはまだ完了していませんが、ここでの問題には関係ないと思います)。

public void onMessageReceived(TBTGuestConnect sender, String message) {
    for(TBTGuestConnect guestConnect : _clientSockets)
        if(guestConnect != sender)
            guestConnect.sendMessage(message);
}

クライアントは「GuestConnect」オブジェクトとして保存されます。ここでは、それらを設定する方法を示します (GuestConnect.java):

public class GuestConnect {


   private StringBuilder _currentMessage;
   private BufferedReader _is;
   private PrintStream _os;
   private Socket _clientSocket = null;

   private String _hostname;

   private boolean _running = false;

   public GuestConnect(String hostname) {
    _hostname = hostname;

    _currentMessage = new StringBuilder();
   }

clientSocket の初期化 (まだ GuestConnect.java):

private void initSocket() {

    if(_clientSocket==null)
    {
        // Try to open a server socket on given port
        // Here is the fail when I called it from another device
        try {
            _clientSocket = new Socket(_hostname, ServerConnect.CONNECT_SOCKET_PORT);
        } catch (IOException e) {
            Log.w("GuestSocket", e.toString());
        }
    }

    // Create a socket object from the ServerSocket to listen and accept
    // connections.
    // Open input and output streams
    try {
        _is = new BufferedReader(new InputStreamReader(_clientSocket.getInputStream()));
        _os = new PrintStream(_clientSocket.getOutputStream());


    } catch (IOException e) {
        Log.w("GuestSocket", e.toString());

    }
}

繰り返しますが、同じクラスに通信部分があります。

    initSocket();

    _running = true;

    performConnectionStarted();
    try {
        while (_running) {
            String received = _is.readLine();
            _currentMessage.append(received);
            if (received.contains(ServerConnect.CONNECT_SOCKET_MESSAGE_END)) {
                String finalMsg = _currentMessage.toString().substring(0, _currentMessage.lastIndexOf(ServerConnect.CONNECT_SOCKET_MESSAGE_END));
                performMessageReceived(finalMsg);
                _currentMessage.setLength(0);
            }

        }
    } catch (IOException e) {
        Log.w("GuestSocket", e.toString());
        performError(e);
    } finally {

        try {
            _os.close();
            _is.close();
            _clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
            performError(e);
        }

        _clientSocket = null;
    }

次に、このメソッドからメッセージを送信できます。

public void sendMessage(String toSend) {
    if (_running)
        _os.println(toSend+ServerConnect.CONNECT_SOCKET_MESSAGE_END);
    else
        throw new IllegalStateException("Send message : Connection isn't started !");
}

問題は、グローバル インターネット IP アドレスを使用してこれを機能させるにはどうすればよいかということです。

より一般的には、同じ wifi ローカル IP アドレスとインターネット IP アドレスの技術的な違いは何ですか?

4

2 に答える 2

1

簡単なので最後から始めます-ローカルIPアドレスはプライベートであり、ローカルネットワークからは無効です(そして表示されません)。ローカルネットワーク外の誰かが直接アクセスすることはできませんが、パブリックでホストにアクセスできますIP アドレス。プライベート アドレスは一意ではなく、パブリック IP アドレスは一意であり、(通常は) インターネット上のどのポイントからでも見ることができます。この件については、 http://en.wikipedia.org/wiki/Network_address_translationの詳細があります。

3g ネットワークに関しては、こちらをご覧ください。3g IP を使用して iPhone に接続できますか? ここでServerSocket accept() は Android で接続を受け入れません。だから多分それはできない

于 2013-03-26T20:34:04.640 に答える
1

これがあなたにとって重要かどうかはわかりませんが、わが国ではほとんどの 3G アカウントが ISP によって着信接続からブロックされています。ポートのブロックを解除するには、申請する必要があります。ブロックを解除しない ISP もあれば、解除する ISP もあります。

DVR を 3G モデムに接続しようとしたときに、これを見つけました。

于 2014-11-18T12:45:53.530 に答える