java - 程序卡在 ObjectInputStream 构造函数处

标签 java sockets

嘿,我最近 2-3 天正在尝试调试这个程序。问题是,我正在构建一个客户端服务器体系结构,并且所有客户端在使用 Socket 连接的一定时间间隔后 ping 服务器(及其信息)。因此,在服务器端,当我尝试构建 ObjectOutputStream 时,程序会卡住。这是客户端的代码。

 public void pingUpdate(){
    Thread pingThread = new Thread() {
    public void run() {
        while(true) {
             try { 
                ping_socket = new Socket( "localhost", 11111 );
                ObjectOutputStream ping_objectOutputStream = new ObjectOutputStream( ping_socket.getOutputStream( ) );
                ping_objectOutputStream.flush();

                ping_objectOutputStream.writeObject( user );

                ping_objectOutputStream.close();

                ping_socket.close( );

             }catch (Exception exception) {
               exception.printStackTrace();
            }
           }
   };
    pingThread.start();
}

这是服务器的代码

  public void run() {
while ( true ) {
      try {

            System.out.println("Server Listening" );

            Socket client = null;

            client = serverSock.accept();
            System.out.println("Accepted" );

             InputStream inputStream = client.getInputStream();

             System.out.println("Input stream established" );

             ObjectInputStream ois = new ObjectInputStream( inputStream );

              System.out.println("Object streams established" );

              User user = ( User ) ois.readObject( );

              System.out.println("Object read" );

               ois.close( );
               client.close( );
             }
              catch (Exception e){
                     e.printStackTrace();
                 }
         }
    }

服务器程序打印直到“输入流已建立”并卡住。尽管我在客户端刷新了输出流,但我不知道为什么会发生这种情况。谢谢。

最佳答案

我无法重现挂起的客户端。我认为它必须如何将对象写入流而不随后刷新流,因为流仅在满时或关闭之前刷新。请使用finally block 关闭套接字和流。

我重写了您的源代码并发送字符串“Hallo,Server”而不是用户对象(您提供的代码中缺少该对象)。我在发送后添加了一点延迟,以免连接淹没服务器。

我已经在使用 JDK 1.8 Update 102 的 Win 8.1 上测试了代码,现在可以正常工作了。

客户:

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class Client{

   public static void main(String[] args){

      new Client().pingUpdate();
   }

   public void pingUpdate(){

      Thread pingThread = new Thread(){

         @Override
         public void run(){

            while(true){
               Socket ping_socket = null;
               ObjectOutputStream ping_objectOutputStream = null;
               try{
                  ping_socket = new Socket("localhost",
                                           11111);
                  ping_objectOutputStream = new ObjectOutputStream(ping_socket.getOutputStream());

                  ping_objectOutputStream.writeObject("Hallo, Server");
                  ping_objectOutputStream.flush();
               }
               catch(Exception exception){
                  exception.printStackTrace();
               }
               finally{
                  try{
                     if (ping_objectOutputStream != null){
                        ping_objectOutputStream.close();
                     }
                  }
                  catch(IOException e){
                     e.printStackTrace();
                  }
                  try{
                     if (ping_socket != null){
                        ping_socket.close();
                     }
                  }
                  catch(IOException e){
                     e.printStackTrace();
                  }
               }

               // wait some time for the next ping
               try{
                  Thread.sleep(1000);
               }
               catch(InterruptedException e){
                  e.printStackTrace();
               }
            }
         }
      };
      pingThread.start();
   }
}

服务器:

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server{

   public void servePingUpdate(){

      Thread pingThread = new Thread(){

         @Override
         public void run(){

            ServerSocket serverSock = null;
            try{
               serverSock = new ServerSocket(11111);

               while(true){
                  Socket client = null;
                  ObjectInputStream ois = null;

                  try{
                     System.out.println("Server Listening");

                     client = serverSock.accept();
                     System.out.println("Accepted");

                     InputStream inputStream = client.getInputStream();

                     System.out.println("Input stream established");

                     ois = new ObjectInputStream(inputStream);

                     System.out.println("Object streams established");

                     String message = (String) ois.readObject();

                     System.out.println("Object read: " + message);
                  }
                  catch(Exception e){
                     e.printStackTrace();
                  }
                  finally{
                     try{
                        if (ois != null){
                           ois.close();
                        }
                     }
                     catch(IOException e){
                        e.printStackTrace();
                     }
                     try{
                        if (client != null){
                           client.close();
                        }
                     }
                     catch(IOException e){
                        e.printStackTrace();
                     }
                  }
               }
            }
            catch(IOException e1){
               e1.printStackTrace();
            }
            finally{
               try{
                  if (serverSock != null){
                     serverSock.close();
                  }
               }
               catch(IOException e){
                  e.printStackTrace();
               }
            }
         }
      };
      pingThread.start();
   }

   public static void main(String[] args){

      new Server().servePingUpdate();
   }
}

编辑:TCP 协议(protocol)需要一些时间来进行 TCP 握手,服务器需要一些时间通过 System.out 输出行并关闭套接字。

如果没有等待,客户端会在 1-2 秒后抛出 java.net.BindException:地址已在使用中:连接,因为服务器没有可用端口。 对于低延迟 ping,UDP 协议(protocol)更好,请参阅 example code for a UDP pinger或者保持套接字打开并在每次 ping 时重复使用它。

关于java - 程序卡在 ObjectInputStream 构造函数处,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40417331/

相关文章:

c - 如何防止sendfile函数中的SIGPIPE

c# - TCPClient套接字错误0x80004005的原因

c - socket()中 "protocol"为SOCK_DGRAM或SOCK_STREAM时是否需要指定 "type"?

java - 一个 SQL 查询中的多个语句,还是使用 Batch?

java - 在没有任何 Java 库的情况下对 3D 形状进行编程

java - 将条件转移到多个方法中

java - 在 JNI 下以 native 代码获取 java 缓冲区的最有效方法是什么?

java - 谷歌云语音NoSuchFieldError : CONTEXT_SPAN_KEY

Java RegEx 与 Pattern 类多组

sockets - UDP 响应