簡體   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