当前位置: 首页 > 知识库问答 >
问题:

Java套接字异常:套接字关闭和空值

籍靖
2023-03-14

我想创建能够与多个客户端连接的服务器,但我总是收到“套接字关闭”异常或从输入流中读取空值,以前我认为这是由于以错误的方式关闭套接字连接引起的,所以我发布了这个主题,但现在似乎这不是问题所在。

服务器方法

//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:套接字已关闭…',如下所示

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

我研究了很长时间,仍然找不到到底是什么导致了这些异常和数据丢失问题,以及服务器运行一段时间后是否存在可能导致内存泄漏问题的潜在风险?

共有1个答案

彭阳朔
2023-03-14

问题似乎出在您的HandlerThread的构造函数中:

您正在调用this.start();,这真的不应该。尤其是在同时使用ExecutorService时!

(在这种特定情况下,您正在创建一个新线程并启动它,同时告诉您的执行者运行相同的代码。最后,同一代码将在单个套接字上运行两次,这可能会导致各种问题,其中一个线程将关闭套接字,而另一个线程仍在尝试从中读取。这就是例外的真正来源。)

解决方案:

不要扩展线程,而是让您的HandlerThread只实现可运行的接口。

一旦您将该类的实例交给执行器,它将负责运行您的run()方法;不需要自己开始任何线程。

 类似资料:
  • 我最近一直在玩套接字,但是我遇到了一个问题…当我从服务器接收数据时,我得到一个“java.net.套接字异常:套接字关闭”异常。我没有在任何地方关闭套接字,事实上,我唯一使用关闭()的地方是扫描仪上从System.in读取文本; 以下是我的代码: 客户: 服务器: 数据包发送者: 客户端接收器: 数据包接收器:

  • 我在tomcat日志中每两分钟就会出现一次异常: 警告nio。ReadHandler[hz.\u hzInstance\u 1\u xyz.IO.thread-in-2]-[127.0.0.1]:5702[xyz][3.2.3]hz_hzInstance_1_xyz。木卫一。线程2关闭套接字到endpoint地址[127.0.0.1]:5701,原因:java。木卫一。EOFEException:

  • 我尝试用Java套接字API制作基本的Java聊天应用程序。但是当客户端终止时,它会引发以下异常, socketException:套接字关闭 我认为即使套接字已经关闭,BufferedReader流仍然尝试读取行消息。 但我不知道当客户端终止时,何时以及如何关闭BufferedReader流和套接字连接。 我完全被这部分卡住了。有什么想法吗?

  • 我正在为客户机发送对象到服务器,在服务器端修改该对象,并将其重新发送到客户机。将对象从客户机发送到服务器很好,它工作正常,但当我将对象发送回来时,它给出了异常,Socket关闭。这里是代码。IntString和ParentObj是我要发送对象的类。 服务器类 用于发送和接收对象的Send_recv类。

  • 因此,我有一个客户机wich连续发送和接收数据消息,wich工作正常,然而,当我关闭/停止客户机时,我会得到以下单行错误: 尽管我试图关闭插座--最终封闭了。现在我的问题是为什么我会收到这个错误,这个行为是否正常,以及如何正确处理这个错误。下面是我的代码:

  • 问题内容: 我试图呼吁一个非常繁重的过程。平均工作时间估计为9-10分钟。 当我执行该过程时,我为一个巨大的数字设置了超时时间:99999999。 2分钟后,出现以下错误: java.net.SocketTimeoutException:读取超时 我尝试对其进行更多处理,并将超时设置为3000,并且在预期的3秒钟后出现了相同的错误。 您对为什么将其设置为最大120000 有任何想法吗? 问题答案: