[英]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.