[英]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.