[英]Java network code not sending
我正在編寫我的第一個非平凡的Java應用程序,它使用:
這是一個IM程序。 當我發送消息時,服務器不會輸出它應該的內容。 對不起,這個描述太糟糕了,但我不知道如何進一步縮小問題范圍。
public class MachatServer {
//snip
public static void sendMessage(int targetId, int fromId, String message) {
ConnectedClient targetClient = getClient(targetId);
// Also runs
System.out.println("Sending message: " + message + "\n\nfrom " + fromId + " to " + targetId);
targetClient.addOutCommand("/message:" + fromId + ":" + message + "\n");
}
}
class ConnectedClient implements Runnable {
public void run() {
String contact;
contact = s.getInetAddress().toString();
System.out.println("Connected to " + contact);
try {
out.write("/connected" + "\n");
out.flush();
String command;
while(true) {
if(shouldExit) {
s.close();
break;
}
if(in.hasNextLine()) {
command = in.nextLine();
commandProcessor.addInCommand(command);
}
Thread.sleep(100);
}
} catch(Exception e) {
e.printStackTrace();
}
}
// snip
public void addOutCommand(String command) {
commandProcessor.addOutCommand(command);
//
// My guess is that the problem is with this method as the next line
// Does not print out.
//
//
System.out.println("" + thisId + " recieved to send: " + command);
}
}
class CommandProcessor implements Runnable {
// snip
public void run() {
String currentCommandIn;
String currentCommandOut;
while(true) {
try {
currentCommandIn = inQueue.poll();
if(currentCommandIn != null) {
System.out.println("Processing: " + currentCommandIn);
String[] commandArr = CommandParser.parseRecievedCommand(currentCommandIn);
if(commandArr[0].equalsIgnoreCase("message")) {
int target = Integer.parseInt(commandArr[1]);
String message = commandArr[2];
// This definetly runs
System.out.println("Message sending to: " + target);
MachatServer.sendMessage(target, this.conId, message);
} else if(commandArr[0].equalsIgnoreCase("quit")) {
// Tell the server to disconnect us.
MachatServer.disconnect(conId);
break;
}
currentCommandOut = outQueue.poll();
if(currentCommandOut != null) {
try {
out.write(currentCommandOut + "\n");
System.out.println(currentCommandOut + "sent");
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch(Exception e) {
e.printStackTrace();
}
public synchronized void addOutCommand(String command) {
if(command != null) {
try {
outQueue.push(command);
} catch(Exception e) {
System.out.println(command);
e.printStackTrace();
}
// Does not print
System.out.println("Ready to send: " + command);
} else {
System.out.println("Null command recieved");
}
//snip
}
完整的源代碼在我的github上 ,以防我錯誤地縮小了問題。
預期輸出應該是當我telnet並發送“/ message:0:test”時,它應該向ID為0的客戶端發送“/ message: myid :test”。實際輸出是什么。
這可能不是一個完整的答案,但是您的代碼存在一些可能導致問題的嚴重問題,因此您應該首先解決這些問題。
首先, CommandProcessor.run
的循環正在忙等待,即它不斷運行。 您應該使用阻止操作。 此外,從兩個不同的線程訪問inQueue
和outQueue
,因此您需要在每次訪問時進行同步。 我建議使用實現java.util.concurrent.BlockingQueue
接口的東西來解決這兩個問題。 最后,在檢查完整代碼時,您似乎還需要同步訪問ConnedtedClient.shouldExit
字段(我相信您可以使用`java.util.concurrent.atomic.AtomicBoolean作為替代,但我不確定) 。
這可能是導致問題的原因:由於CommandProcessor.run
沒有在任何事情上進行同步(或訪問任何易變的東西),Java虛擬機可以假設外部沒有任何內容可以修改它檢查的任何東西,所以從理論上講, run
方法首先注意到inQueue
和outQueue
都是空的,它可以將整個方法優化為空,因為它可以假設它是唯一可以修改它們的東西。 但是我不知道這是否真的會在實踐中發生,因為JVM需要對LinkedList
實現有很多了解,並注意到線程只是在循環中進行這兩個檢查。 但最好是安全,因為這樣你的代碼就可以保證工作。
outQueue
字段在CommandProcessor中未初始化,您注釋掉了printStackTrace()
,它可以幫助您解決問題。
也許問題是你發送的數據很短......
幾年前,我的一個朋友遇到了類似的問題,結果發現數據被緩沖,直到有足夠的數據發送...
它與優化網絡流量有關...我相信當他最終解決它時,他提到了一種叫做“Nagle算法”的東西......
希望這可以提供一些幫助......
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.