簡體   English   中英

多線程客戶端/服務器應用程序Java問題

[英]Multithreaded Client/Server application java issue

這是我的第一篇文章,所以如果我做錯了,請糾正我。

我正在嘗試制作多線程客戶端/服務器應用程序。 在沒有線程的情況下制作基本的1對1客戶端/服務器應用程序沒有問題,但是我希望每個客戶端分別與服務器對話,並且每個客戶端只接收屬於控制台中特定客戶端的消息。 這是我無法使其正常工作的地方。

我在線上看了一些教程,但是我嘗試在Eclipse中進行調試沒有任何運氣。 我希望應用程序執行以下操作:

如果我運行服務器和2個客戶端,則希望能夠在客戶端上寫一條消息,並使服務器返回消息和消息號而不跳過數字。

客戶1:

留言編號:0。您說:您好!

消息編號:1.您說:怎么了!

客戶2:

消息編號:0。您說:嘿,服務器!

消息編號:1.您說:您現在在做什么?

它與我運行的第一個客戶端一起工作,並完美地增加了消息號,但是當我創建第二個客戶端時,它凍結了,所以我想我的問題是套接字聲明還是線程方式。 (也許socket.close()在某處丟失了?)

我知道應用程序還有其他缺陷,但是請記住,這只是使用線程的學校作業。

預先感謝您是否願意提供幫助。 :)

服務器代碼:

public class Server extends Thread 
{   
  DataInputStream in;
  DataOutputStream out;
  ServerSocket listener;

public Server() throws IOException
{      
    try 
    {
        while (true) 
        {
            listener = new ServerSocket(9090);
            Socket socket = listener.accept(); 
            System.out.println("Test");
            ThreadServer ts = new ThreadServer(socket);
            Thread t1 = new Thread(ts);
            t1.start();   
        }
    }
    finally 
    {
        listener.close();
    }   
}

public static void main(String[] args) throws IOException 
{
    new Server();
}
}

客戶代碼:

public class Client extends JFrame 
 {      
   DataOutputStream dos;
   BufferedReader input;
   String answer = null;
   String textString;
   Socket s = new Socket("localhost", 9090);

public Client() throws IOException
{
    JButton btn = new JButton("run");
    final JTextField txf = new JTextField(10);
    btn.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {             
            try 
            {   
                dos = new DataOutputStream(s.getOutputStream());
                textString = txf.getText();
                dos.writeUTF(textString);
                dos.flush();        
                input = new BufferedReader(new InputStreamReader(s.getInputStream()));
                answer = input.readLine();                      
            } 
            catch (Exception e1) 
            {
                e1.printStackTrace();
            }           
                System.out.println(answer); 
            }       
    });
    setLayout(new GridLayout(2,2));
    add(btn);
    add(txf);
    setVisible(true);
    pack();
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

public static void main(String[] args) throws IOException 
{
    new Client();
}
}

ThreadServer代碼:

public class ThreadServer implements Runnable
{
  DataInputStream in;
  DataOutputStream out;

public ThreadServer (Socket socket) throws IOException
{       
    int i = 0;  

    try 
    {
        while (true) 
        {            
            in = new DataInputStream(socket.getInputStream());
            out = new DataOutputStream(socket.getOutputStream());

            try 
            {
                String message = in.readUTF();          
                PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                out.println("Message no: " + i + ". You said: " + message);                  
                out.println("Message no: " + i);
            }
            catch(Exception e) 
            {
                e.printStackTrace();
            }
            i++;
        }
    }
    finally 
    {
        socket.close();
    }
}

@Override
public void run() {
    // TODO Auto-generated method stub

}
  }

讓我嘗試解決它。

  • 僅創建一個ServerSocket while循環移到行下方。 將其放在while循環之前。

     listener = new ServerSocket(9090); 
  • ThreadServer的構造函數的代碼移動到run()方法,因為它實現了Runnable但行為卻不像Runnable類。

     public ThreadServer(Socket socket) throws IOException { this.socket=socket; } @Override public void run() { ... //code from constructor } 
  • 在服務器類中,您向客戶端編寫了兩行,但客戶端僅讀取了一行。 刪除多余的行,如下所示

     out.println("Message no: " + i + ". You said: " + message); //out.println("Message no: " + i); 

最后一個建議:

始終在調用readUTF()之前檢查輸入,如下所示:

if (in.available() > 0) {
    try {
        String message = in.readUTF();
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        out.println("Message no: " + i + ". You said: " + message);
        //out.println("Message no: " + i);
    } catch (Exception e) {
        e.printStackTrace();
    }
    i++;
}

您的ThreadServer在構造函數中無限循環,而不是在run方法中循環。 這真是太糟了。 您應該在run方法中放置該代碼。

您還應該遵循注釋中的建議並移動套接字的創建。

-編輯-

對於您的ThreadServer也是如此,不要在循環中執行套接字初始化。 只是閱讀。

稍后您可能還會發現,您需要為客戶端增加一個線程。 現在看來,每個客戶端只能在單擊“執行操作”按鈕時才能接收消息,而這可能並不是您想要的。 這將暴露一些您將要處理的同步問題,但是大多數gui庫實際上可以為您提供幫助。 自從我處理揮桿動作已經很長時間了。

-再次編輯-此外,請閱讀有關異常處理的內容。 您應該確定要捕獲IO異常的位置,而不是將try / catch隨機嵌套並在拋出異常時聲明方法。

暫無
暫無

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

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