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 アドレスの技術的な違いは何ですか?