Java Socket 连接仅在 Debug模式下有效

标签 java sockets debugging

我想实现一个服务器,它在特定端口上无休止地监听以从许多客户端接收数据(从不并行,仅串行)。我尝试的第一件事是运行服务器,然后连续启动几个客户端(一个接一个)。

这听起来很容易实现,但实际上我遇到了问题,只有当我在服务器代码中至少有一个断点的 Debug模式下运行代码时,代码才能工作(但与正常运行它时没有相同的错误一个断点),对我来说很奇怪。

但是这里是服务器代码:

public class TaskExecutionServer {
    public TaskExecutionServer(final int port) {
        new Thread() {
            @Override
            public void run() {
                try {
                    int counter = 0;
                    ServerSocket serverSocket = new ServerSocket(port);

                    while(true) {
                        System.out.println("Waiting for client...");
                        Socket socket = serverSocket.accept();
                        System.out.println("Accepted");
                        InputStream inputStream = socket.getInputStream();
                        ObjectInputStream objectStream = new ObjectInputStream(inputStream);
                        while(inputStream.available() > 0 ) {
                            String to = (String)objectStream.readObject();
                            System.out.println(to);
                            System.out.println(++counter);
                        }
                        objectStream.close();
                        inputStream.close();

                        System.out.println("Closing socket");
                        socket.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
    public static void main(String args[]) {
        new TaskExecutionServer(2003);
    }
}

这里是客户端代码:

public class TaskSenderClient {
  public static void main(String args[]){
    try{
        Socket s = new Socket("localhost",2003);
        OutputStream os = s.getOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(os);

        oos.writeObject("test");
        oos.close();
        os.close();
        s.close();
    }catch(Exception e){
        System.out.println("Client exception");
        e.printStackTrace();
    }
  }
}

这是在服务器代码行 System.out.println("Accepted"); 中使用断点在 Debug模式下运行时的控制台输出:

Waiting for client...
Accepted
test
1
Closing socket
Waiting for client...
Accepted
test
2
Closing socket
Waiting for client...
Accepted
test
3
Closing socket
Waiting for client...

以及在正常模式下运行时的输出/在 Debug模式下没有断点:

Waiting for client...
Accepted
test
1
Closing socket
Waiting for client...
Accepted
Closing socket
Waiting for client...
Accepted
Closing socket
Waiting for client...

我没有发现任何异常...有人可以帮忙吗?这是我第一次尝试在 java 中重新使用套接字连接。

编辑:检查 inputStream.available 返回不同的值

我刚刚在服务器代码中的 while 之前添加了一个 System.out.println(inputStream.available());。这打印

  • 始终7 处于带断点的 Debug模式
  • 7(在第一次运行中)和 0(在所有其他尝试中)之后在非 Debug模式/没有断点

编辑 2:首先等到 inputStream.available != 0 此解决方案也适用于我。但是,我在这里删除了这个代码片段,因为检查 available() 似乎不是正确的方法! -> 查看解决方案!

编辑 3:新的服务器代码,它使用 NonEmptyInputStream 检查每个 PushbackInputStream 的非空流:

因为它使用了 EOFException,所以它对我来说似乎不是一个最佳解决方案,所以我也删除了这个代码片段(而是参见下面的解决方案)。在下面的评论中讨论了“正确”代码中异常的使用...

最佳答案

InputStream.available()可以回0如果还没有数据,意味着客户端还没有发送一些数据或者至少还没有到达。如果添加断点,客户端将有更多时间发送数据。

您可以添加逻辑,例如您的客户端首先发送它写入的对象数量,服务器读取该数量,然后在停止读取之前读取该数量的对象。

另一种可能性是插入 PushbackInputStreamObjectInputStream 之间和 InputStream然后做 read()PushbackInputStream 上, 检查 -1 的结果这意味着流结束,如果不是 -1 , 使用 unread()在使用 ObjectInputStream 之前将读取的字节推回流中方法。

这里有一个用最后一个模式重写的最初发布的类的示例:

public class TaskExecutionServer {
    public TaskExecutionServer(final int port) {
        new Thread() {
            @Override
            public void run() {
                try {
                    int counter = 0;
                    ServerSocket serverSocket = new ServerSocket(port);

                    while(true) {
                        System.out.println("Waiting for client...");
                        Socket socket = serverSocket.accept();
                        System.out.println("Accepted");
                        InputStream inputStream = socket.getInputStream();
                        PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream);
                        ObjectInputStream objectStream = new ObjectInputStream(pushbackInputStream);
                        for(int i; (i = pushbackInputStream.read()) != -1;) {
                            pushbackInputStream.unread(i);
                            String to = (String) objectStream.readObject();
                            System.out.println(to);
                            System.out.println(++counter);
                        }
                        objectStream.close();
                        pushbackInputStream.close();
                        inputStream.close();

                        System.out.println("Closing socket");
                        socket.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    public static void main(String args[]) {
        new TaskExecutionServer(2003);
    }
}

或再次使用 try-with-resources,这比手动关闭 AutoClosable 更可取

public class TaskExecutionServer {
    public TaskExecutionServer(final int port) {
        new Thread() {
            @Override
            public void run() {
                try (ServerSocket serverSocket = new ServerSocket(port)) {
                    int counter = 0;

                    while(true) {
                        System.out.println("Waiting for client...");
                        try (Socket socket = serverSocket.accept();
                             InputStream inputStream = socket.getInputStream();
                             PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream);
                             ObjectInputStream objectStream = new ObjectInputStream(pushbackInputStream)) {
                            System.out.println("Accepted");
                            for(int i; (i = pushbackInputStream.read()) != -1;) {
                                pushbackInputStream.unread(i);
                                String to = (String) objectStream.readObject();
                                System.out.println(to);
                                System.out.println(++counter);
                            }
                            System.out.println("Closing socket");
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    public static void main(String args[]) {
        new TaskExecutionServer(2003);
    }
}

关于Java Socket 连接仅在 Debug模式下有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39124379/

相关文章:

c++ - 可移植轻量级 C++ 套接字包装器

windows - 线程命令在 WInDbg 中不起作用

Xcode/AppCode 中的 IOS Swift 调试 - 我无法查看我的字典内容

java - RSA 身份验证问题

java - 如何在 Jersey-Test 中发布 JSON 请求

c - fprintf 失败,但 fputc 工作正常?

php - 您如何调试 CodeIgniter 应用程序?

java - 给定数据库结构可以在运行时更改,如何处理并发 SQL 更新

java - JSF 状态最初保存到服务器和 session 超时传输到客户端?

java - 我应该把这个参数放在哪里以及如何运行这个程序?