私の元の質問に答えたので、これはこの質問の続きですが、バグは解決しませんでした。
質問:
- この行にぶら下がっているコードを修正するにはどうすればよいですか inStream.readline()
私の意図:
- これは、outMessageがあるかどうかのチェックをループするスレッド内にあり、ある場合はメッセージを送信します。
- 次に、インストリームに何かがあるかどうかをチェックし、ある場合は、メインアクティビティのハンドラーに送信します。
- 最後に、1秒間スリープしてから、もう一度確認します。
- これにより、ソケットを開閉しなくても、何度も読み取り/書き込みができるようになります。
問題:
- 読み取りと書き込みは改善されていますが、それでも正しく機能していません
今何が起こっているのか:
- outMessageが値で初期化されている場合、サーバーとの接続時に、ソケットは次のようになります。
- 値を書き込んでフラッシュします(サーバーは受信して応答します)
- outMessageの値を更新します(ハードコーディングの方法に応じて、nullまたは "x"に)
- サーバーからの応答メッセージを読み取って表示します
- 次のループに再び入る
- outMessageをnullに設定すると、それをスキップして、ifステートメントが正しくハングします。それ以外の場合、outMessageを文字列(たとえば「x」)に設定すると、ifステートメント全体を通過してからハングします。
- ハングするコードは、 inStream.readline()呼び出しのいずれかです(現在、コメントアウトされています)。
追加情報:-接続したら、「送信」ボックスに入力し、送信(outMessage値を更新)してから切断します。再接続すると、値が読み取られ、同じ行でスタックするまでシーケンスが再度実行されます。
参照された質問以降の変更点:-outMessageとconnectionStatusの両方を「volatile」にしました-必要な場所に行末区切り文字を追加しました。
コード:
public void run() {
while (connectionStatus != TCP_SOCKET_STATUS_CONNECTED) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
while (connectionStatus == TCP_SOCKET_STATUS_CONNECTED) {
try {
if (outMessage != null){
OutStream.writeBytes(outMessage + "\n");
OutStream.flush();
sendMessageToAllUI(0, MAINACTIVITY_SET_TEXT_STATE, "appendText" , "OUT TO SERVER: " + outMessage);
outMessage = "x";
}
Thread.sleep(100);
// if (InStream.readLine().length() > 0) {
String modifiedSentence = InStream.readLine();
sendMessageToAllUI(0, MAINACTIVITY_SET_TEXT_STATE, "appendText" , "IN FROM SERVER: " + modifiedSentence);
// }
Thread.sleep(1000);
} catch (IOException e) {
connectionLost();
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
ソケットを作成するスレッド:
public void run() {
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) {
connectionFailed();
} catch (SocketTimeoutException e) {
connectionFailed();
} catch (IOException e) {
// Close the socket
try {
tempSocketClient.close();
} catch (IOException e2) {
}
connectionFailed();
return;
}
}
サーバ:
public static void main(String[] args) throws IOException {
String clientSentence;
String capitalizedSentence;
try {
ServerSocket welcomeSocket = new ServerSocket(8888);
SERVERIP = getLocalIpAddress();
System.out.println("Connected and waiting for client input!\n Listening on IP: " + SERVERIP +"\n\n");
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
while(true)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
clientSentence = inFromClient.readLine();
System.out.println("clientSentance == " + clientSentence);
String ip = connectionSocket.getInetAddress().toString().substring(1);
if(clientSentence != null)
{
System.out.println("In from client ("+ip+")("+ System.currentTimeMillis() +"): "+clientSentence);
capitalizedSentence = clientSentence.toUpperCase() + '\n';
outToClient.writeBytes(capitalizedSentence + '\n');
System.out.println("Out to client ("+ip+"): "+capitalizedSentence);
}
}
} catch (IOException e) {
//if server is already running, it will not open new port but instead re-print the open ports information
SERVERIP = getLocalIpAddress();
System.out.println("Connected and waiting for client input!\n");
System.out.println("Listening on IP: " + SERVERIP +"\n\n");
}
}
前もって感謝します!
編集:
- 更新後にサーバーコードを追加しました
- ソケットのSoTimoutを設定してみましたが、それを元に戻しました