当我的 SECOND 客户端连接到服务器时,出现此错误:
Exception in thread "main" java.net.SocketException: Connection reset
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:200)
at java.base/java.io.DataInputStream.readLine(DataInputStream.java:518)
at Main.main(Main.java:24)
我不知道我在做什么错。
第一 客户端正常工作
我的代码:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class Main {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(50505);;
Socket socket;
while (true) {
socket = serverSocket.accept();
while(socket.isConnected()) {
String v;
DataInputStream in;
InputStream in_sock;
in_sock = socket.getInputStream();
in = new DataInputStream(in_sock);
v = in.readLine();
System.out.println(v);
OutputStream output = socket.getOutputStream();
DataOutputStream out = new DataOutputStream(output);
out.writeChars("123\n");
out.writeChars("123\n");
out.writeChars("123\n");
}
}
}
}
PS:如何在stackoverflow上共享错误?喜欢代码吗?
答案 0 :(得分:2)
因此,就像其他人说的那样,最大的问题是,由于缺少多线程,您的服务器只能接受一个连接。
现在您的服务器正在等待与指定端口的连接
socket = serverSocket.accept();
然后在您的套接字仍处于连接状态时,从套接字读取一行,将其打印到System.out,然后循环写回到套接字。现在出现了这个问题,因为下一次客户端尝试连接到您的serverSocket时,它不再接受连接,因为您的代码陷入了从一个Socket读取和写入数据的循环中。
解决此问题的方法是按照上面Milen提到的方式引入多线程。
您的代码应如下所示。
public class Main {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(50505);
while (true) {
Socket socket = serverSocket.accept();
SocketHandler h = new SocketHandler(socket);
h.start();
}
}
}
public class SocketHandler extends Thread{
Socket clientSock;
public SocketHandler(Socket sock){
clientSock = sock;
}
public void run(){
while(clientSock.isConnected()) {
String v;
DataInputStream in;
InputStream in_sock;
in_sock = socket.getInputStream();
in = new DataInputStream(in_sock);
v = in.readLine();
System.out.println(v);
OutputStream output = socket.getOutputStream();
DataOutputStream out = new DataOutputStream(output);
out.writeChars("123\n");
out.writeChars("123\n");
out.writeChars("123\n");
}
}
}
现在此代码具有一个接受连接的循环,并为每个连接产生一个新线程!
我建议您看几件事。首先,如果检查ServerSocket的Java文档,您将看到此构造函数
ServerSocket(int port, int backlog)
Creates a server socket and binds it to the specified local port number, with the specified backlog.
待办事项是服务器套接字可以保留并存储在某种缓冲区中直到可以接受的传入连接数。如果您的接受循环在创建套接字处理程序的过程中客户端正在连接,则这很有用。我建议将其设置为您期望的最大客户数量。
其次,在Javadocs中查找Thread类。要成功扩展Thread,您需要覆盖run()。此方法是线程将使用的方法。要生成线程,请调用ThreadObject.start()。您可以将start()看作只是调用run()。
答案 1 :(得分:1)
来自Oracle的“ Writing the Server Side of a Socket”教程:
...服务器可以通过使用线程(每个客户端连接每个线程一个线程)同时为它们提供服务。
这种服务器中逻辑的基本流程是:
while (true) { accept a connection; create a thread to deal with the client; }
线程根据需要读取和写入客户端连接。
在该教程中,您还将找到指向服务器(KKMultiServer)和线程(KKMultiServerThread)示例实现的链接。