多线程客户端/服务器应用程序java问题
这是我的第一篇帖子,如果我做错了,请纠正我 我正在尝试制作一个多线程的客户机/服务器应用程序。我可以在没有线程的情况下创建一个基本的1对1客户机/服务器应用程序,但是我希望每个客户机单独与服务器对话,并且每个客户机只在控制台中接收属于特定客户机的消息。这就是我不能让它工作的地方 我在网上看了一些教程,并尝试在Eclipse中进行调试,但没有任何运气。 我希望应用程序执行的操作: 如果我运行服务器和2个客户机,我希望能够在客户机上编写消息,并使服务器返回消息和消息编号,而不跳过编号 客户1: 消息编号:0。你说:你好 信息编号:1。你说:怎么了 客户2: 消息编号:0。你说:嘿,服务器 信息编号:1。你说:你现在在做什么 它与我运行的第一个客户机一起工作,并完美地增加messagenumber,但当我创建第二个客户机时,它会冻结,因此我想我的问题要么是套接字声明,要么是线程方式。(可能某个地方缺少socket.close()) 我知道这个应用程序还有其他一些缺陷,但请记住,这只是一个学校的线程作业 如果有人愿意帮忙,请提前感谢。:) 服务器代码:多线程客户端/服务器应用程序java问题,java,multithreading,sockets,client,chat,Java,Multithreading,Sockets,Client,Chat,这是我的第一篇帖子,如果我做错了,请纠正我 我正在尝试制作一个多线程的客户机/服务器应用程序。我可以在没有线程的情况下创建一个基本的1对1客户机/服务器应用程序,但是我希望每个客户机单独与服务器对话,并且每个客户机只在控制台中接收属于特定客户机的消息。这就是我不能让它工作的地方 我在网上看了一些教程,并尝试在Eclipse中进行调试,但没有任何运气。 我希望应用程序执行的操作: 如果我运行服务器和2个客户机,我希望能够在客户机上编写消息,并使服务器返回消息和消息编号,而不跳过编号 客户1: 消息
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();
}
}
线程服务器代码:
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
}
}
您的
ThreadServer
在构造函数中无限循环,而不是run
方法。
这很糟糕。run方法是您应该放置代码的地方
您还应该遵循注释中的建议并移动套接字创建
-编辑-
对于ThreadServer
,同样如此,不要在循环中执行套接字初始化。只是阅读
稍后您可能还会发现,您需要为客户机添加一个额外的线程。就现在这样
似乎每个客户端只能在单击“执行的操作”按钮时接收消息,
这可能不是你想要的。这将暴露一些同步问题
这是您必须处理的,但大多数gui库实际上可能会在这方面帮助您。
我很久没有处理swing了
-重新编辑-
此外,请阅读异常处理。你应该决定你要去哪里
捕获IO异常,而不是随机嵌套try/catch和声明方法
就像扔它们一样。让我试着解决它
- 只创建一个
。在循环时从ServerSocket
移动到行下方。将它放在
之前,而
循环
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++;
}
你不应该做
listener=newserversocket(9090)代码>在循环中,因为端口周围的第二次将很忙,创建将失败。只需在循环之前创建一次服务器套接字,并在循环中多次调用同一服务器套接字上的accept。一个建议是,将您在server和ThreadServer类的构造函数中编写的代码添加到各自的运行方法中。非常感谢。现在它起作用了。不过,我很高兴我很亲近。:)感谢您的输入,我的异常处理还不是很好,所以您指出这一点很好。到目前为止,我们只编写了7个月的代码。