3

私はこれを機能させるためにさまざまな実装を試みており、StackOverflowとAndroid Developersで解決策を探しましたが、プログラミングの経験があまりなく、このブロックをコードに正しく機能させることができません。

私の意図:

  1. これは、outMessageがあるかどうかのチェックをループするスレッド内にあり、ある場合はメッセージを送信します。
  2. 次に、インストリームに何かがあるかどうかをチェックし、ある場合は、メインアクティビティのハンドラーに送信します。
  3. 最後に、1秒間スリープしてから、もう一度確認します。
  4. これにより、ソケットを開閉しなくても、何度も読み取り/書き込みができるようになります。

問題:

  • ソケットを閉じるまで、アウトストリームはフラッシュされません。flush()は効果がないようです。

私の要求:

  • 上記のようにこのコードを正しく機能させるために必要な変更を投稿してください(理由を説明する注釈があれば大歓迎です。他の同様の質問/回答へのリンクは私が学ぶのに役立ちますが、私はそれらをいくつか見てきました数週間で動作しなくなるため、上記のように動作させるために必要な変更されたコードも含めるようにしてください。よろしくお願いします。

他の:

  • インストリームおよび/またはアウトストリームで行末文字を探す必要があるかどうか疑問に思っていますか?
  • ここではTCP_NODELAYのようなものを使用しますか?
  • 与えることができるどんな追加情報も非常に高く評価されます。私はこのことをよく学びたいのですが、現在は何も機能させることができません。

コード:

 public void run() {                        
        while (connectionStatus == TCP_SOCKET_STATUS_CONNECTED) {
            try {   
                if (outMessage != null){
                   OutStream.writeBytes(outMessage);
                   OutStream.flush();           
                   outMessage = ("OUT TO SERVER: " + outMessage);           
                // socketClient.close();     
                   sendMessageToAllUI(0, MAINACTIVITY_SET_TEXT_STATE, "appendText" , outMessage);
                   outMessage = null;               
                } 
                if (InStream != null) {                     
                    String modifiedSentence = InStream.readLine();      
                    sendMessageToAllUI(0, MAINACTIVITY_SET_TEXT_STATE, "appendText" , "\n" + "IN FROM SERVER: " + modifiedSentence);
            }
            Thread.sleep(1000);
        } catch (IOException e) {               
            connectionLost();
            break;
        } catch (InterruptedException e) {
                e.printStackTrace();
            }
    }                           
}

ソケットを作るスレッド:

public void run() {
        if(I) Log.i(LOGTAG, "Attempt Connection with IP: " + serverIP + " ...");
        setName("AttemptConnectionThread");
        connectionStatus = TCP_SOCKET_STATUS_CONNECTING;
        try {
            SocketAddress sockaddr = new InetSocketAddress(serverIP, port);
            tempSocketClient = new Socket(); // Create an unbound socket

            // This method will block no more than timeoutMs. If the timeout occurs, SocketTimeoutException is thrown.
            tempSocketClient.connect(sockaddr, timeoutMs);
            OutStream = new DataOutputStream(tempSocketClient.getOutputStream());
            InStream = new BufferedReader(new InputStreamReader(tempSocketClient.getInputStream()));
            socketClient = tempSocketClient;
            socketClient.setTcpNoDelay(true);
            connected(); 
        } catch (UnknownHostException e) {
            if(I) Log.i(LOGTAG,"     ...UnknownException e: e.getMessage() shows: " + e.getMessage());
            connectionFailed();
        } catch (SocketTimeoutException e) {
            if(I) Log.i(LOGTAG,"     ...SocketTimoutException e: e.getMessage() shows: " + e.getMessage());
            connectionFailed();
        } catch (IOException e) {
            if(I) Log.i(LOGTAG,"     ...caught on run()");
            // Close the socket
            try {
                tempSocketClient.close();
            } catch (IOException e2) {
                Log.e(LOGTAG, "unable to close() socket during connection failure", e2);
            }
            if(I) Log.i(LOGTAG,"     ...IOException e: e.getMessage() shows: " + e.getMessage());
            connectionFailed();
            return;
        }
    } 

オンラインで見つけて、これを実サーバーに移植するまで使用しているJavaサーバー:

public class Server {

private static String SERVERIP;

/**
 * @param args
 * @throws IOException
 */

public static void main(String[] args) throws IOException {
    String clientSentence;
    String capitalizedSentence;

    try {
        ServerSocket welcomeSocket = new ServerSocket(8888);
        getIp();
        System.out.println("Connected and waiting for client input!\n");

        while (true) {
            Socket connectionSocket = welcomeSocket.accept();
            BufferedReader inFromClient = new BufferedReader(
                    new InputStreamReader(connectionSocket.getInputStream()));
            DataOutputStream outToClient = new DataOutputStream(
                    connectionSocket.getOutputStream());

            clientSentence = inFromClient.readLine();
            String ip = connectionSocket.getInetAddress().toString()
                    .substring(1);
            System.out.println("In from client (" + ip + "): "
                    + clientSentence);
            if (clientSentence != null) {
                capitalizedSentence = clientSentence.toUpperCase() + '\n';
                System.out.println("Out to client (" + ip + "): "
                        + capitalizedSentence);
                outToClient.writeBytes(capitalizedSentence + "\n");
            }

        }
    } catch (IOException e) {
        // if server is already running, it will not open new port but
        // instead re-print the open ports information
        getIp();
        System.out
                .println("Server connected and waiting for client input!\n");

    }
}

private static void getIp() {
    InetAddress ipAddr;
    try {
        ipAddr = InetAddress.getLocalHost();
        System.out.println("Current IP address : "
                + ipAddr.getHostAddress());

    } catch (UnknownHostException e) {
        e.printStackTrace();
    }
}
}
4

2 に答える 2

3

あなたは消費者で行を読んでいると思いますが、あなたは行を書いていません。そのため、消費者はEOSを取得して1つの大きな行を配信するまでブロックします。必要に応じて送信時にラインターミネータを追加します。

于 2012-08-07T21:36:15.787 に答える
1

これらは短いメッセージ(< MSS)であるため、スタックがNagleのアルゴリズムを実装している可能性があります。サーバーはある種の遅延ACKを実行していますか?可能であれば、トレースをキャプチャして、反対側からの保留中の確認応答があるかどうかを確認する必要があります。

どちらの場合でも、TCP_NODELAY役立つはずです。

于 2012-08-07T14:54:56.770 に答える