代码之家  ›  专栏  ›  技术社区  ›  Macha

Java网络代码未发送

  •  1
  • Macha  · 技术社区  · 17 年前

    • 网络
    • 图形用户界面
    • 线程

    这是一个即时通讯程序。当我发送消息时,服务器不会输出它应该输出的内容。很抱歉,这个描述太糟糕了,但我不知道如何进一步缩小问题的范围。

    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
    }
    

    完整的源代码在 my github ,以防我错误地缩小了问题的范围。

    粘虫 :test“发送给ID为0的客户端。实际输出为零。

    3 回复  |  直到 17 年前
        1
  •  2
  •   Grandpa    17 年前

    田野 outQueue 在CommandProcessor中未初始化,并且您注释掉了 printStackTrace()

        2
  •  3
  •   JaakkoK    17 年前

    这可能不是一个完整的答案,但是代码中有一些严重的问题可能是问题的原因,因此您应该首先修复这些问题。

    首先,循环 CommandProcessor.run inQueue 和 outQueue 从两个不同的线程访问,因此每次访问都需要同步。我建议使用一些实现 java.util.concurrent.BlockingQueue 接口来解决这两个问题。最后,在检查完整代码时,似乎还需要同步对 ConnedtedClient.shouldExit

    这可能是你问题的原因:因为 CommandProcessor.run 如果Java虚拟机不在任何东西上同步(或访问任何易变的东西),它可以假设外部的任何东西都不能修改它所检查的任何东西,因此理论上,当 run 方法首先注意到 和 出列 都是空的,它可以将整个方法优化为零,因为它可以假设这是唯一可以修改它们的东西。但我不知道这在实践中是否真的会发生,因为JVM需要了解很多关于 LinkedList 请注意,线程只是在循环中执行这两个检查。但最好是安全,因为这样你的代码才能保证工作。

        3
  •  -1
  •   Quagmire    17 年前

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

    希望这能对你有所帮助。。。