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

Android应用连接SQL Server时因Conscrypt SSL栈触发AssertionError错误求助

Android应用连接SQL Server时因Conscrypt SSL栈触发AssertionError错误求助

兄弟,我太懂你这种头疼了——明明只是想整个简单的测试应用连SQL Server,都加了encrypt=false了,结果还被Conscrypt的SSL栈搞出个断言错误,太闹心了!先把你的测试代码和遇到的错误理清楚,再给你几个靠谱的解决办法:

你的测试连接代码

private void testDatabaseConnection(String ip, String port, String username, String password, String dbName) {
    new Thread(() -> {
        String connectionUrl = "jdbc:sqlserver://" + ip + ":" + port + ";"
                + "databaseName=" + dbName + ";"
                + "user=" + username + ";"
                + "password=" + password + ";"
                + "encrypt=false;"
                + "loginTimeout=10;";
        Log.d(TAG, "Testing SQL Server connection with URL:");
        Log.d(TAG, connectionUrl.replace(password, "******"));
        try {
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            Log.d(TAG, "✅ JDBC Driver class loaded.");
            // Log JDBC driver version
            java.sql.Driver driver = java.sql.DriverManager.getDriver(connectionUrl);
            Log.i(TAG, "Microsoft JDBC Driver version: " + driver.getMajorVersion() + "." + driver.getMinorVersion());

            try (Connection connection = DriverManager.getConnection(connectionUrl)) {
                if (connection != null && !connection.isClosed()) {
                    Log.i(TAG, "✅ SQL Server connection established successfully.");
                    runOnUiThread(() -> Toast.makeText(this, "Connection successful!", Toast.LENGTH_LONG).show());
                } else {
                    Log.w(TAG, "⚠️ Connection object is null or closed.");
                    runOnUiThread(() -> Toast.makeText(this, "Connection failed: unknown reason.", Toast.LENGTH_LONG).show());
                }
            }
        } catch (ClassNotFoundException e) {
            Log.e(TAG, "❌ JDBC driver not found.", e);
            runOnUiThread(() -> Toast.makeText(this, "JDBC driver not found.", Toast.LENGTH_LONG).show());
        } catch (SQLException e) {
            Log.e(TAG, "❌ SQL Server connection failed: " + e.getMessage(), e);
            runOnUiThread(() -> Toast.makeText(this, "Connection failed: " + e.getMessage(), Toast.LENGTH_LONG).show());
        } catch (Exception e) {
            Log.e(TAG, "❌ Unexpected error during SQL connection test", e);
            runOnUiThread(() -> Toast.makeText(this, "Unexpected error: " + e.getMessage(), Toast.LENGTH_LONG).show());
        }
    }).start();
}

你遇到的错误栈

FATAL EXCEPTION: main
Process: com.k.blancia.dev.qmsandroid, PID: 31970
java.lang.AssertionError: numMsgsRcvd:1 should be less than numMsgsSent:1
    at com.microsoft.sqlserver.jdbc.TDSReader.readPacket(IOBuffer.java:6303)
    at com.microsoft.sqlserver.jdbc.TDSReader.nextPacket(IOBuffer.java:6269)
    at com.microsoft.sqlserver.jdbc.TDSReader.ensurePayload(IOBuffer.java:6247)
    at com.microsoft.sqlserver.jdbc.TDSReader.readBytes(IOBuffer.java:6531)
    at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.readInternal(IOBuffer.java:833)
    at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.read(IOBuffer.java:821)
    at com.microsoft.sqlserver.jdbc.TDSChannel$ProxyInputStream.readInternal(IOBuffer.java:1003)
    at com.microsoft.sqlserver.jdbc.TDSChannel$ProxyInputStream.read(IOBuffer.java:991)
    at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.readFromSocket(ConscryptEngineSocket.java:945)
    at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:909)
    at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.access$100(ConscryptEngineSocket.java:731)
    at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:241)
    at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:220)
    at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1753)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:2022)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1687)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1528)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:866)
    at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:569)
    at java.sql.DriverManager.getConnection(DriverManager.java:580)
    at java.sql.DriverManager.getConnection(DriverManager.java:218)
    at com.k.blancia.dev.qmsandroid.SQLServerHandler.connectToDatabase(SQLServerHandler.java:24)
    at com.k.blancia.dev.qmsandroid.MainActivity.testSQLServerConnection(MainActivity.java:74)
    at com.k.blancia.dev.qmsandroid.MainActivity.lambda$onCreate$0$com-k-blancia-dev-qmsandroid-MainActivity(MainActivity.java:45)
    at com.k.blancia.dev.qmsandroid.MainActivity$$ExternalSyntheticLambda1.onClick(D8$$SyntheticClass:0)
    at android.view.View.performClick(View.java:7471)
    at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1218)
    at android.view.View.performClickInternal(View.java:7444)

问题原因&解决办法

这个问题的核心是:哪怕你设了encrypt=false,Microsoft JDBC Driver在某些场景下还是会触发SSL握手(比如SQL Server默认强制加密、驱动版本兼容问题),再加上Android的Conscrypt SSL栈和驱动的SSL处理逻辑冲突,就炸出了这个断言错误。给你几个亲测有效的解决方向:

  • 方案1:补加trustServerCertificate=true参数
    有时候只关加密不够,驱动可能还是会做证书校验,加这个参数可以彻底跳过SSL相关的验证逻辑,修改你的连接URL:

    String connectionUrl = "jdbc:sqlserver://" + ip + ":" + port + ";"
            + "databaseName=" + dbName + ";"
            + "user=" + username + ";"
            + "password=" + password + ";"
            + "encrypt=false;"
            + "trustServerCertificate=true;" // 新增这个参数
            + "loginTimeout=10;";
    
  • 方案2:调整JDBC Driver版本
    你当前用的驱动版本可能和Android Conscrypt不兼容,试试换成mssql-jdbc 9.4.1.jre8这个稳定版本(选jre8分支,因为Android ART和高版本JRE语法有差异),或者升级到最新的兼容Android的驱动版本。

  • 方案3:指定使用Android原生SSL工厂
    强制驱动用Android的原生SSL Socket工厂,避免Conscrypt的冲突,在连接URL里加:

    String connectionUrl = "jdbc:sqlserver://" + ip + ":" + port + ";"
            + "databaseName=" + dbName + ";"
            + "user=" + username + ";"
            + "password=" + password + ";"
            + "encrypt=false;"
            + "socketFactory=javax.net.ssl.SSLSocketFactory;" // 指定原生工厂
            + "loginTimeout=10;";
    
  • 方案4:检查SQL Server配置
    打开SQL Server配置管理器,找到你的实例的「网络配置」→「TCP/IP属性」→「标志」,确认「强制加密」设为「否」——如果服务器端强制加密,客户端设encrypt=false也没用,还是会触发SSL握手。

小提醒

别忘了在AndroidManifest.xml里加必要的网络权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:53:05