Java で記述された単純な TCP サーバーがあり、ローカル マシンで実行されている TCP サーバーと通信する Android 用の単純な TCP クライアントを作成しようとしています。
サーバーにメッセージを受信させることはできますが、奇妙なことに、Eclipse の [デバイス] ウィンドウからアプリケーション プロセスを停止した後にしかメッセージを受信しません。
Android クライアントには、IP アドレスとポート番号を入力するためのフィールドを含むメイン UI スレッドがあります (これはすべて正常に機能するため、コードは含めません)。接続ボタンをクリックすると、新しい ASyncTask が開始され、TCP ソケットの作業が行われます。
ConnectionTask クラスの doInBackground メソッドのコードは次のとおりです。
protected Void doInBackground(Void... params)
{
String authMessage = "Authorize";
boolean connected=false;
try
{
Socket clientSocket = new Socket();
SocketAddress serverAddress = new InetSocketAddress(address,port);
Log.v("Connection Thread", serverAddress.toString());
clientSocket.connect(serverAddress, 15);
if(clientSocket.isConnected())
{
connected = true;
Log.v("Connection Thread", "Connection Successful");
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.writeBytes(authMessage);
Log.v("Connection Thread", "Sent Auth Message");
String response = inFromServer.readLine();
Log.v("TCP Client", "Response: " + response);
hash = computeHash(response.getBytes());
//send the computed hash to the server
outToServer.writeBytes(hash);
outToServer.close();
inFromServer.close();
clientSocket.close();
}
else
{
Log.v("Connection Thread", "Not Connected yet...");
}
}
catch (Exception e)
{
Log.v("Connection Thread", e.getMessage());
}
return null;
}
接続ボタンを押すと、エミュレーターで「Sent Auth Message」までのログが表示されますが、DDMS を介してプロセスを強制終了するまで、サーバーは「Authorize」というメッセージを受信しません。
サーバーコードは次のとおりです。
public class Server
{
private static SecureRandom random = new SecureRandom();
public static void main(String argv[]) throws Exception
{
String rawClientMessage,lcClientMessage;
ServerSocket welcomeSocket = new ServerSocket(5000);
System.out.println("Starting Server...");
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
rawClientMessage = inFromClient.readLine();
if(rawClientMessage!=null)
{
lcClientMessage = rawClientMessage.toLowerCase() + '\n';
System.out.println("Received Message! Contents: " + rawClientMessage);
if(lcClientMessage=="authorize")
{
System.out.println("Received auth request message, generating key...");
String key = generateKey();
//send key back
outToClient.writeBytes(key);
System.out.println("Key sent!");
}
}
try
{
inFromClient.close();
outToClient.close();
connectionSocket.close();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
private static String generateKey()
{
return new BigInteger(130, random).toString(32);
}
}
編集:
何が起こるかを段階的に要約すると次のようになります。
- サーバーを起動します(接続の待機をブロックし、「サーバーが起動しました...」と表示されます)
- 192.168.0.100 ポート 5000 を Android クライアントに入力し、「接続」ボタンを押します
- クリックすると ASyncTask が作成され、ソケット コードが上に表示されます
- サーバーコンソールにはまだ何も受信されていません...
- (接続をもう一度押しても何も起こりません) (LogCat は「Send Auth Message」ログまで読み取ります)
- Eclipse デバイス ウィンドウからエミュレーターのプロセスを強制終了します
- サーバー コンソールに次のように表示されます。Received Message! 内容:承認(接続を2回クリックするとメッセージが2回表示される)
基本的に、メッセージを保存しているようで、プログラムの終了後にそれらをすべてネットワークに送信しています。
どんな助けでも大歓迎です、ありがとう!メイン UI スレッドと、ASyncTask を拡張する ConnectionTask クラスの残りの部分を含む、より多くのコードを投稿できます (必要な場合)。
ありがとう!