繁体   English   中英

Java网络代码不发送

[英]Java network code not sending

我正在编写我的第一个非平凡的Java应用程序,它使用:

  • 联网
  • 一个GUI
  • 线程

这是一个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的循环正在忙等待,即它不断运行。 您应该使用阻止操作。 此外,从两个不同的线程访问inQueueoutQueue ,因此您需要在每次访问时进行同步。 我建议使用实现java.util.concurrent.BlockingQueue接口的东西来解决这两个问题。 最后,在检查完整代码时,您似乎还需要同步访问ConnedtedClient.shouldExit字段(我相信您可以使用`java.util.concurrent.atomic.AtomicBoolean作为替代,但我不确定) 。

这可能是导致问题的原因:由于CommandProcessor.run没有在任何事情上进行同步(或访问任何易变的东西),Java虚拟机可以假设外部没有任何内容可以修改它检查的任何东西,所以从理论上讲, run方法首先注意到inQueueoutQueue都是空的,它可以将整个方法优化为空,因为它可以假设它是唯一可以修改它们的东西。 但是我不知道这是否真的会在实践中发生,因为JVM需要对LinkedList实现有很多了解,并注意到线程只是在循环中进行这两个检查。 但最好是安全,因为这样你的代码就可以保证工作。

outQueue字段在CommandProcessor中未初始化,您注释掉了printStackTrace() ,它可以帮助您解决问题。

也许问题是你发送的数据很短......

几年前,我的一个朋友遇到了类似的问题,结果发现数据被缓冲,直到有足够的数据发送...

它与优化网络流量有关...我相信当他最终解决它时,他提到了一种叫做“Nagle算法”的东西......

希望这可以提供一些帮助......

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM