gpt4 book ai didi

java - 关闭时写入后无法访问 Socket 的 InputStream 的内容

转载 作者:行者123 更新时间:2023-11-30 10:12:57 24 4
gpt4 key购买 nike

我正在尝试读取刚刚关闭的套接字输入流的全部内容。但是,如果我只是尝试读取它正常工作,我会不断尝试同时写入该套接字的输出流。看起来写入它会“破坏”套接字的输入流,并且无法读取剩余的内容。

拿我做的这个小例子来说明我的问题:

@Test
public void socketTest() throws Throwable
{
new Thread(() -> {
try
{
ServerSocket serverSocket = new ServerSocket(5555);

while(true)
{

//keep listening
Socket socket = serverSocket.accept();

InputStream in = socket.getInputStream();

System.out.println(in.read());

Thread.sleep(2000);

try
{
socket.getOutputStream().write(3);
}
catch(Throwable ex)
{
System.out.println("Error writing");
ex.printStackTrace();
}

System.out.println(in.read());

in.close();
socket.close();
System.exit(0);
}
}
catch(Throwable ex)
{
System.out.println("Error reading");
ex.printStackTrace();
}
}).start();

Thread.sleep(100); //you might need this
Socket socket = new Socket("localhost", 5555);
OutputStream out = socket.getOutputStream();
out.write(1);
out.write(2);
out.close();
socket.close();

synchronized(this)
{
wait();
}
}

我得到输出:

1
java.net.SocketException: Software caused connection abort: recv failed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.net.SocketInputStream.read(SocketInputStream.java:223)
at net.jumpai.test.SocketTTest.lambda$socketTest$0(SocketTTest.java:55)
at java.lang.Thread.run(Thread.java:745)
Error reading

但是 2 从未被读取,并且在流中写入 3 从未出错。我不在乎在流中写入是否抛出,但我想阅读 2。有什么办法可以做到这一点吗?

我在 Windows 7 上使用 jdk1.8.0_91。即使在更新到 jdk1.8.0_181(现在是最新版本)后,我也可以重现这个问题。我还可以在另一台装有 Java 1.8.0_111 的 Windows 7 计算机上重现。

无法在 ArchLinux open-jdk1.8.0_172 上重现错误,这是否意味着它是 java 版本的错误?它似乎确实与 Windows 或至少与 Oracle 的实现有关。

最佳答案

看到该行为可以很容易地在我的任何版本的 2 台 Windows 机器上重现,但不能在任何 Linux 或 Mac 系统上重现,我怀疑这是 Oracle 的 JVM 中的错误,open-jdk 不存在。

这个错误非常烦人,如果有人可以发布解决方法,我将不胜感激。同时,我向 Oracle 提交了错误报告:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8208479

尝试构建一个解决方法,我提供了这个可以检查您的系统是否有错误。

public static boolean hasOracleSocketBug()
{
try
{
int port = 10000;

while(!PortChecker.portAvailable(port))
port++;

ServerSocket serverSocket = new ServerSocket(port);

int fPort = port;
new Thread(() -> {
try
{
Socket socket = new Socket("localhost", fPort);
OutputStream out = socket.getOutputStream();
out.write(1);
out.write(2);
out.close();
socket.close();
}
catch(Exception ex)
{
try
{
serverSocket.close();
}
catch(IOException ignored) {}
}
}).start();

Socket socket = serverSocket.accept();

InputStream in = socket.getInputStream();
in.read();
socket.getOutputStream().write(3);

try
{
in.read();
}
catch(Exception ex)
{
socket.close();
return true;
}

in.close();
socket.close();
return false;
}
catch(Throwable ignored)
{
return false;
}
}

public static boolean portAvailable(int port)
{
ServerSocket ss = null;
try
{
ss = new ServerSocket(port);
ss.setReuseAddress(true);
return true;
}
catch(IOException ignored)
{
return false;
}
finally
{
if(ss != null)
{
try
{
ss.close();
}
catch(IOException ignored) {}
}
}
}

关于java - 关闭时写入后无法访问 Socket 的 InputStream 的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51580965/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com