我想创建能够与多个客户端连接的服务器,但我总是收到“Socket Closed”异常或从输入流中读取 NULL 值,之前我认为这是由于以错误的方式关闭套接字连接引起的,所以我发布了这个topic , 但现在看来这不是问题。
服务器方法
//here I use thread pool to solve concurrency issue
public static void main(String[] args) {
try{
ExecutorService service = Executors.newFixedThreadPool(4);
ServerSocket serverSocket = new ServerSocket();
while (true) {
//keep listening
Socket socket = serverSocket.accept();
service.execute(new HandlerThread(socket));
}
}catch(Exception ex){
ex.printStackTrace();
}
}
HandlerThread 类
public class HandlerThread extends Thread{
private Socket socket;
private BufferedReader in;
public HandlerThread(Socket socket) throws IOException {
this.socket = socket;
this.start();
}
public void run(){
try {
//Caches is a singleton class, which used to store the received data from client
Caches caches = Caches.getInstance();
//32 line
in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
String line = in.readLine();
//caches.list is an ArrayList
synchronized (caches.globalCaches) {
if (null != line) {
caches.globalCaches.add(line);
}
}
System.out.println(line);
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端模拟器
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
for(int i = 0 ; i < 40; i++){
Thread.sleep(2000);
test test1 = new test();
test1.start();
}
}
public static class test extends Thread{
public void run(){
try {
Socket socket = new Socket("localhost", 5050);
PrintStream out = new PrintStream(socket.getOutputStream());
out.println("Hello Server!");
out.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
异常和问题
在客户端模拟器之前启动服务器,客户端模拟器没有任何异常,但是在服务器端,并没有收到所有数据,从控制台打印信息,我看到'null','Hello Server','java.net.SocketException: Socket is closed...',如下所示
Hello Server
null
null
Hello Server
java.net.SocketException: Socket is closed
Hello Server
at java.net.Socket.getInputStream(Socket.java:876)
at com.icubeidea.core.threads.HandlerThread.run(HandlerThread.java:32)
Hello Server
我研究了很久,还是没找到到底是什么原因造成的异常和数据丢失的问题,还有服务器运行一段时间后会不会出现内存泄露问题的潜在风险?
最佳答案
问题似乎出在您的 HandlerThread
的构造函数中:
你正在调用 this.start();
你真的不应该。尤其是同时使用 ExecutorService
时!
(在这种特定情况下,您正在创建一个新线程并 start()
它,同时告诉您的执行程序运行相同的代码。最后,相同的代码将在单个套接字上运行两次,这可能会导致各种问题,其中一个线程将关闭套接字,而另一个线程仍在尝试从中读取。这就是异常实际出现的地方来自.)
解决方法:
不要扩展Thread,而是让您的HandlerThread
只实现Runnable
接口(interface)。
一旦您将该类的实例移交给执行程序,它将负责运行您的 run()
方法;无需自己启动任何线程。
关于Java 套接字异常 : Socket Closed and null value,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25032827/