2

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);
       }
}

編集:

何が起こるかを段階的に要約すると次のようになります。

  1. サーバーを起動します(接続の待機をブロックし、「サーバーが起動しました...」と表示されます)
  2. 192.168.0.100 ポート 5000 を Android クライアントに入力し、「接続」ボタンを押します
  3. クリックすると ASyncTask が作成され、ソケット コードが上に表示されます
  4. サーバーコンソールにはまだ何も受信されていません...
  5. (接続をもう一度押しても何も起こりません) (LogCat は「Send Auth Message」ログまで読み取ります)
  6. Eclipse デバイス ウィンドウからエミュレーターのプロセスを強制終了します
  7. サーバー コンソールに次のように表示されます。Received Message! 内容:承認(接続を2回クリックするとメッセージが2回表示される)

基本的に、メッセージを保存しているようで、プログラムの終了後にそれらをすべてネットワークに送信しています。

どんな助けでも大歓迎です、ありがとう!メイン UI スレッドと、ASyncTask を拡張する ConnectionTask クラスの残りの部分を含む、より多くのコードを投稿できます (必要な場合)。

ありがとう!

4

3 に答える 3

3

あなたは行を読んでいますが、行を書いていません。readLine()ラインターミネータを受信するまでブロックされ、送信することはありません。また、受信するデータはバイナリであるため、とにかくそれを読み取ろうとしてはいけませreadLine()ん。データストリームを再検討してください。

于 2012-04-16T08:18:47.083 に答える
2

writeBytes(message)バイトを出力ストリームに書き込みますが、ストリームがフラッシュされるまでパイプに送信されません。アプリを強制終了すると、ストリームが閉じられ、ストリームが閉じられる前に、ストリームが自動的にフラッシュされます。

outToClient.flush()あなたが後に追加すると、outToClient.writeBytes(authMessage)あなたはロッキンになると思います。

于 2012-04-16T06:07:27.263 に答える
1

エミュレーターでアプリを実行する場合は、ポートをリダイレクトする必要があります。そうしないと、クライアントとサーバーを通信できません。 見てみる

于 2012-04-16T06:27:19.490 に答える