简体   繁体   English

Java网络代码不发送

[英]Java network code not sending

I'm writing my first non-trivial Java app that uses: 我正在编写我的第一个非平凡的Java应用程序,它使用:

  • networking 联网
  • a GUI 一个GUI
  • threads 线程

It's a IM program. 这是一个IM程序。 When I send a message, the server doesn't output what it should. 当我发送消息时,服务器不会输出它应该的内容。 I'm sorry this description is so bad, but I don't know how to narrow the problem down further. 对不起,这个描述太糟糕了,但我不知道如何进一步缩小问题范围。

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
}

The full source code is at my github , in case I have narrowed the problem down incorrectly. 完整的源代码在我的github上 ,以防我错误地缩小了问题。

The expected output should be when I telnet in and send "/message:0:test", it should send "/message: myid :test" to the client with ID 0. The actual output is nothing. 预期输出应该是当我telnet并发送“/ message:0:test”时,它应该向ID为0的客户端发送“/ message: myid :test”。实际输出是什么。

This is probably not a complete answer, but there are a few serious issues with your code that could be the cause of your problem, so you should fix those first. 这可能不是一个完整的答案,但是您的代码存在一些可能导致问题的严重问题,因此您应该首先解决这些问题。

First, the loop in CommandProcessor.run is busy-waiting, ie, it runs constantly. 首先, CommandProcessor.run的循环正在忙等待,即它不断运行。 You should use blocking operations. 您应该使用阻止操作。 Also, inQueue and outQueue are accessed from two different threads so you need synchronization on every access. 此外,从两个不同的线程访问inQueueoutQueue ,因此您需要在每次访问时进行同步。 I recommend using something implementing the java.util.concurrent.BlockingQueue interface to solve both issues. 我建议使用实现java.util.concurrent.BlockingQueue接口的东西来解决这两个问题。 And finally, when checking your full code, it appears that you also need to synchronize access to the ConnedtedClient.shouldExit field (I believe you can use `java.util.concurrent.atomic.AtomicBoolean as a replacement but I'm not sure). 最后,在检查完整代码时,您似乎还需要同步访问ConnedtedClient.shouldExit字段(我相信您可以使用`java.util.concurrent.atomic.AtomicBoolean作为替代,但我不确定) 。

And the reason why this could be the cause of your problem: Since CommandProcessor.run is not synchronizing on anything (or accessing anything volatile), the Java virtual machine can assume that nothing from outside can modify anything it examines, so in theory, when the run method first notices that inQueue and outQueue are both empty, it can optimize the whole method into nothing, as it can assume that it is the only thing that can modify them. 这可能是导致问题的原因:由于CommandProcessor.run没有在任何事情上进行同步(或访问任何易变的东西),Java虚拟机可以假设外部没有任何内容可以修改它检查的任何东西,所以从理论上讲, run方法首先注意到inQueueoutQueue都是空的,它可以将整个方法优化为空,因为它可以假设它是唯一可以修改它们的东西。 But I don't know whether this can actually happen in practice, as the JVM needs to know quite a bit about the LinkedList implementation and notice that the thread is just doing these two checks in a loop. 但是我不知道这是否真的会在实践中发生,因为JVM需要对LinkedList实现有很多了解,并注意到线程只是在循环中进行这两个检查。 But it's always best to be safe because that way your code is guaranteed to work. 但最好是安全,因为这样你的代码就可以保证工作。

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

Maybe the problem is that the data you send is to short.... 也许问题是你发送的数据很短......

A friend of mine had a similar problem a couple of years ago, and it turned out the data was being buffered until it had enough data to send... 几年前,我的一个朋友遇到了类似的问题,结果发现数据被缓冲,直到有足够的数据发送...

It had something to do with optimizing the amount of network traffic... I believe he mentioned something called "Nagle's algorithm" when he finally solved it.... 它与优化网络流量有关...我相信当他最终解决它时,他提到了一种叫做“Nagle算法”的东西......

Hope this can be of some help... 希望这可以提供一些帮助......

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

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