簡體   English   中英

objectOutputStream 的 readObject() 方法沒有接收到寫入到 Client 的 inputStream 上的 object?

[英]The readObject() Method of objectOutputStream is not receiving the object written on the inputStream to the Client?

目的是將坐標從一個客戶端(正在繪制)傳輸到連接到服務器的所有客戶端,然后在它們各自的面板上繪制,但客戶端中的 readObject() 似乎永遠不會獲取數據。 輸入正確執行 go 到服務器,但從服務器,其他客戶端無法收聽。

當使用 BufferedStream 或 DataInput/OutputStream any Other 時,輸入似乎滯后或行為不端。 所以更喜歡ObjectOutputStream。 程序快照。

客戶端在后台線程listenData 中偵聽輸入。

客戶代碼 -

公共 class 客戶擴展 JFrame {

private static final long serialVersionUID = 1L;
private Coordinates crdntsToSend;
private Coordinates crdntsReceived;
private JPanel contentPane;
private Socket socket;
private ObjectOutputStream toServerPipe;
private ObjectInputStream fromServerPipe;
private JPanel paintPanel;

public Clients(String name,int port,String ip) {
    setResizable(false);
    setTitle("Skribbl");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(600,550);
    createConnection(ip,port);
    listen();
}

private void createConnection(String ip,int port)
{
    try {
        socket = new Socket(ip,port);
        toServerPipe = new ObjectOutputStream(socket.getOutputStream());
        fromServerPipe = new ObjectInputStream(socket.getInputStream());
        toServerPipe.flush();
        userInterfaceSetter();
    } catch (IOException e) {
        System.out.println("Port Not Found!!!");
        return;
    }
}

private void userInterfaceSetter()
{
    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception e1) {
        e1.printStackTrace();
    } 
    getContentPane().setLayout(null);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    GridBagLayout gbl_contentPane = new GridBagLayout();
    gbl_contentPane.columnWidths = new int[] {0, 0};
    gbl_contentPane.rowHeights = new int[]{0, 0, 0};
    gbl_contentPane.columnWeights = new double[]{1.0, Double.MIN_VALUE};
    gbl_contentPane.rowWeights = new double[]{1.0, 0.0, Double.MIN_VALUE};
    contentPane.setLayout(gbl_contentPane);
    
    paintPanel = new JPanel();
    paintPanel.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            drawOnPanel(e.getX(),e.getY());
        }
    });
    paintPanel.addMouseMotionListener(new MouseMotionAdapter() {
        @Override
        public void mouseDragged(MouseEvent e) {
            drawOnPanel(e.getX(),e.getY());
        }
    });
    paintPanel.setBackground(new Color(175, 238, 238));
    GridBagConstraints gbcPaintPanel = new GridBagConstraints();
    gbcPaintPanel.insets = new Insets(10, 10, 10, 10);
    gbcPaintPanel.fill = GridBagConstraints.BOTH;
    gbcPaintPanel.gridx = 0;
    gbcPaintPanel.gridy = 0;

    contentPane.add(paintPanel, gbcPaintPanel);
    
    JLabel lblScore = new JLabel("Score: ");
    GridBagConstraints gbclblScore = new GridBagConstraints();
    gbclblScore.insets = new Insets(0, 0, 10, 0);
    gbclblScore.anchor = GridBagConstraints.WEST;
    gbclblScore.gridx = 0;
    gbclblScore.gridy = 1;
    contentPane.add(lblScore, gbclblScore);
}

private void drawOnPanel(int x,int y)
{
    Graphics g = paintPanel.getGraphics();
    g.fillOval(x, y, 7, 7);
    sendData(x,y);
}

private void sendData(int x, int y) {
    try {
        crdntsToSend = new Coordinates(x,y);
        toServerPipe.writeObject(crdntsToSend);
        toServerPipe.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
private void listen()
{
    SwingWorker<Void, String> listenData = new SwingWorker<Void, String>() {
        boolean go = true;
        String[] receivedData;
        String str;
        @Override
        protected Void doInBackground() throws Exception {
            while(go)
            {
                crdntsReceived = (Coordinates) fromServerPipe.readObject();
                str= crdntsReceived.toString();
                publish(str);
            }
            return null;
        }

        @Override
        protected void process(List<String> chunks) {
             receivedData = str.split(" ");
             drawOnPanel(Integer.parseInt(receivedData[0]),Integer.parseInt(receivedData[1]));
        }
        
    };
    listenData.execute();
}

}

ServerHandler 代碼(服務器線程) -

package theskribbl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class HandleClient implements Runnable 
{
  private Socket[] socket;
  private ObjectInputStream fromClients;
  private ObjectOutputStream toClients;
  private static int count = 0;
  private int temp;
  public HandleClient(Socket[] socket, int count)
  {
  HandleClient.count = count;
  temp=count;
  this.socket=socket;
  try 
  {
      fromClients = new ObjectInputStream(socket[count].getInputStream());
      toClients = new ObjectOutputStream(socket[count].getOutputStream());
      toClients.flush();
  } 
  catch (IOException e) 
  {
        e.printStackTrace();
   }
   }
    @Override
    public void run() 
    {
    int i;
    Coordinates coordinate;
    while(true) 
    {
        i=0;
        try 
    {
          coordinate = (Coordinates) fromClients.readObject();
          System.out.println(coordinate.toString());
          while(i<=count) 
    {
              if(i!=temp)
              {
                    toClients = new ObjectOutputStream(socket[i].getOutputStream());
                    toClients.writeObject(coordinate);
                    toClients.flush();
              }
              i++;
          }
        }
        catch (Exception e) 
    {
            System.out.println("Something Went Wrong");
            return;
        }
    } 
    } 
    }

客戶代碼 - https://repl.it/@GirirajSingh/skribbl#Clients.java

登錄客戶端的代碼 - https://repl.it/@GirirajSingh/skribbl#Login.java

處理客戶端(服務器端)的代碼 - https://repl.it/@GirirajSingh/skribbl#HandleClient.java

服務器代碼 - https://repl.it/@GirirajSingh/skribbl#ServerClass.java

ObjectOutputStreamObjectInputStream構造函數調用必須匹配 - 創建ObjectOutputStream時,它會發送 header ,創建ObjectInputStream時必須接收該 header 。

我沒有時間研究代碼,但看起來 output 流在每次服務器發送某些內容時都在循環中構建。 客戶每次收到坐標時是否都會重新打開輸入?

查看ObjectOutputStreamObjectInputStream的文檔以獲得更好的解釋。 最好從一個(非常)簡單的原型開始:一台服務器,一個客戶端,並且只發送幾個(測試 = 固定)坐標。


doInBackGround() (在SwingWorker內部)可能拋出了一個異常! 建議在SwingWorker終止后(在其覆蓋的done()內)調用get()方法來檢查這一點 - 如果計算拋出異常,這將拋出ExecutionException ,其中將包含有關異常的信息。

SwingWorker中添加如下代碼:

@Override
protected void done() {
    try {
        get();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

注意:此代碼不是為了解決問題,只是為了顯示可能的錯誤

您所說的標頭不匹配,實際上它們是匹配的,因為它們是通過同一個套接字初始化的。 使用 DataOutputStream/DataInputStream(write()/read() ) 進行相同的過程,但是在此過程中,數據會泄漏,因為如果鼠標快速拖動,則數據會在兩者之間丟失。 所以這就是為什么我想使用 ObjectOutputStream 的 read/writeObject()。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM