You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows平台下TLS 1.3环境Java Socket发送数据后关闭连接触发服务器端异常的问题求助

Windows平台下TLS 1.3环境Java Socket发送数据后关闭连接触发服务器端异常的问题求助

我最近碰到一个挺棘手的问题:写了一段最基础的Java Socket通信代码,在TLS 1.2环境下跑完全正常,但切换到Windows平台的TLS 1.3就直接炸了——Linux上完全没这个问题,甚至把服务器部署在Windows、客户端放Linux也会触发异常,反过来就一切正常。

我的需求其实特别简单:客户端建立SSL连接后发送一次数据,然后直接关闭Socket。结果服务器端在处理的时候,每次都会抛出SocketException,提示连接被主机上的软件中止。我查了相关资料,感觉这应该是不同平台TLS 1.3实现的差异导致的,听说Java有个系统属性可以让TLS 1.3兼容旧的连接关闭行为,但我设置之后完全没效果。我就很疑惑,客户端发完数据就关闭连接这种场景太普遍了,怎么在TLS 1.3下就走不通呢?

服务器端抛出的异常栈:

java.net.SocketException: An established connection was aborted by the software in your host machine
	at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:330)
	at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:355)
	at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:808)
	at java.base/java.net.Socket$SocketInputStream.read(Socket.java:966)
	at java.base/sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:484)
	at java.base/sun.security.ssl.SSLSocketInputRecord.readHeader(SSLSocketInputRecord.java:478)
	at java.base/sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(SSLSocketInputRecord.java:70)
	at java.base/sun.security.ssl.SSLSocketImpl.readApplicationRecord(SSLSocketImpl.java:1465)
	at java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:1069)
	at java.base/java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2897)
	at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2913)
	at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3410)
	at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:954)
	at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:392)
	at TestChallenge/scratch.OO.lambda$main$0(OO.java:36)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
	at --- Async.Stack.Trace --- (captured by IntelliJ IDEA debugger)
	at java.base/java.util.concurrent.FutureTask.<init>(FutureTask.java:151)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.<init>(ScheduledThreadPoolExecutor.java:215)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor.schedule(ScheduledThreadPoolExecutor.java:561)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor.execute(ScheduledThreadPoolExecutor.java:705)
	at TestChallenge/scratch.OO.main(OO.java:30)

完整代码实现:

import java.io.*;
import java.net.*;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.util.concurrent.*;
import javax.net.ssl.*;
import org.jetbrains.annotations.NotNull;

public class OO {
    public static void main(String[] args) throws Exception {
        enum STATE { CURR }

        final SSLContext sslContext = getSslContext();
        final ServerSocketFactory serverSocketFactory = sslContext.getServerSocketFactory();
        final SSLServerSocket serverSocket = (SSLServerSocket) serverSocketFactory.createServerSocket(1888);

        final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(20);

        scheduledExecutorService.execute(() -> {
            while (!serverSocket.isClosed()) {
                try {
                    final SSLSocket socket = (SSLSocket) serverSocket.accept();
                    try {
                        try(final InputStream inputStream = socket.getInputStream()){
                            final ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
                            final Object o = objectInputStream.readObject();
                            System.out.println(o);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    // 尝试过开启SO_Linger,但无效果
                    // socket.setSoLinger(true,10);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        final javax.net.SocketFactory socketFactory = sslContext.getSocketFactory();
        scheduledExecutorService.scheduleWithFixedDelay(() -> {
            try {
                try (final SSLSocket socket = (SSLSocket) socketFactory.createSocket("127.0.0.1", 1888)) {
                    // 客户端侧也尝试过设置SO_Linger,同样无效
                    // socket.setSoLinger(true,10);
                    socket.startHandshake();
                    final OutputStream outputStream = socket.getOutputStream();
                    try (final ObjectOutputStream oo = new ObjectOutputStream(socket.getOutputStream())) {
                        oo.writeObject(STATE.CURR);
                        outputStream.flush();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }, 0, 1, TimeUnit.SECONDS);

        new CountDownLatch(1).await();
    }

    @NotNull
    public static SSLContext getSslContext() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException {
        final KeyStore keyStore = KeyStore.getInstance("pkcs12");
        // 实际代码中会正确加载PKCS12证书文件,此处保留原代码片段
        final String s1 ="MIIKZAIBAzCCCg4GCSqGSIb3DQEHAaCCCf8Eggn7MIIJ9zCCBa4GCSqGSIb3DQEHAaCCBZ8EggWbMIIFlzCCBZMGCyqGSIb3DQEMCgECoIIFQDCCBTwwZgYJKoZIhvcNAQUNMFkwOAYJKoZIhvcNAQUMMCsEFBCnlxptM/N5OqAPpFkoEY3r+0QWAgInEAIBIDAMBggqhkiG9w0CCQUAMB0GCWCGSAFlAwQBKgQQG/RKlEAGPpW5betwGewIlwSCBN";
        // 此处省略SSLContext的完整初始化逻辑
        return SSLContext.getDefault();
    }
}

我已经尝试在客户端和服务器端都设置socket.setSoLinger(true,10),但完全没效果,还是会抛出同样的异常。有没有朋友碰到过类似的问题?或者知道怎么让TLS 1.3下的Socket兼容这种“发完数据就关闭”的场景?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 10:29:31