temz 2023-03-19 13:57 采纳率: 100%
浏览 110
已结题

C# 客户端 与 java 服务端做SSL通信报错

C# 客户端 与 java 服务端做SSL通信
java报错:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: no cipher suites in common

C#报错 :

System.Security.Authentication.AuthenticationException

java的server.jks是用的keytool生成的
C#的client.pfx也是用keytool生成并用keytool转换为pfx文件的
哪个牛人给看看怎么弄,似乎是加密的问题

java代码

 import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.security.KeyStore;
    import java.security.Security;
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLServerSocketFactory;
    import javax.net.ssl.SSLSocket;
    import javax.net.ssl.TrustManagerFactory;
    import com.google.gson.Gson;
     
    public class Server {
        public static void main(String[] args) throws Exception {
            // Set up key manager to do server authentication
            char[] passphrase = "123456".toCharArray();
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(Server.class.getResourceAsStream("e:/server.jks"), passphrase);
     
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, passphrase);
     
            // Set up trust manager to do client authentication
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(ks);
     
            // Set up SSL context
            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
            SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
     
            // Start server
            ServerSocket serverSocket = sslServerSocketFactory.createServerSocket(8080);
     
            System.out.println("Server started on port 8080");
            
           // Gson gson = new Gson();
           // String s = gson.toJson(ob);
            while (true) {
                // Accept client connections
                SSLSocket socket = (SSLSocket) serverSocket.accept();
                InetAddress address =socket.getInetAddress();
                
                System.out.println("Client connected: " + address.getHostAddress());
     
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
     
                // Receive message from client
                String message = reader.readLine();
                System.out.println("Message received: " + message);
     
                // Send message back to client
                writer.println("Message received: " + message);
                writer.flush();
     
                socket.close();
                System.out.println("Client disconnected: " + socket.getInetAddress());
            }
        }
    }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace sslsocket1
{
    internal class SSLClient
    {
        public static void Main(string[] args)
        {
            int port = 8080;

            // 创建 SSL 证书集合
            X509CertificateCollection certCollection = new X509CertificateCollection();
            certCollection.Add(new X509Certificate2("E:\\client.pfx", "123456"));

            // 创建 SSL 流
            TcpClient client = new TcpClient("localhost", port);
            SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);

            try 
            {
                // 客户端认证
                sslStream.AuthenticateAsClient("localhost", certCollection, SslProtocols.Tls12, false);
                Console.WriteLine("客户端已连接服务器");
            }
            catch (AuthenticationException e) 
            {
                Console.WriteLine("Exception: {0}", e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                }
                Console.WriteLine("Authentication failed - closing the connection.");
                client.Close();
                return;

            }

           

            // 向服务器发送消息
            string message = "你好,服务器!";
            byte[] messageBytes = Encoding.UTF8.GetBytes(message);
            sslStream.Write(messageBytes);
            sslStream.Flush();

            Console.WriteLine("已向服务器发送消息:" + message);

            // 接收服务器的响应消息
            byte[] buffer = new byte[2048];
            int bytesRead;

            while ((bytesRead = sslStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                Console.WriteLine("接收到服务器的响应消息:" + response);
            }
            
            // 关闭 SSL 流和客户端 socket
            sslStream.Close();
            client.Close();
        }

        private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
            {
                return true;
            }

            Console.WriteLine("SSL 证书验证失败:" + sslPolicyErrors);
            return false;
        }

    }
}


  • 写回答

7条回答 默认 最新

  • dahe0825 2023-03-19 16:31
    关注

    参考GPT和自己的思路,这个错误提示说明在 SSL 握手阶段,服务端和客户端无法协商出一组共同的加密算法。这个问题可能是由于以下原因导致的:

    1.服务端和客户端协议版本不兼容。可以尝试使用更高或更低版本的 TLS/SSL 协议,看看是否能够解决问题。例如,尝试使用 TLSv1.0,TLSv1.1 或 TLSv1.3 协议。

    2.服务端和客户端支持的加密算法不同。可以在服务端和客户端的 SSL/TLS 配置中检查并确保它们支持相同的加密算法。例如,在服务端配置中添加支持客户端需要的加密算法。

    3.证书不匹配。可以检查证书链是否正确并确保证书是有效的。

    针对你的代码,你可以尝试在 Java 服务端代码中明确指定使用 TLSv1.2 协议,并且指定一组加密算法,例如:

    String[] enabledCipherSuites = { "TLS_RSA_WITH_AES_128_CBC_SHA256" };
    sslContext.getServerSocketFactory().setEnabledCipherSuites(enabledCipherSuites);
    SSLServerSocket sslServerSocket = (SSLServerSocket)sslServerSocketFactory.createServerSocket(8080);
    sslServerSocket.setEnabledCipherSuites(enabledCipherSuites);
    

    同时,在 C# 客户端代码中,也需要指定相同的加密算法,例如:

    SslProtocols enabledProtocols = SslProtocols.Tls12;
    string targetHost = "localhost";
    SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
    sslStream.AuthenticateAsClient(targetHost, null, enabledProtocols, false);
    sslStream.CipherAlgorithm = CipherAlgorithmType.Aes128;
    sslStream.HashAlgorithm = HashAlgorithmType.Sha256;
    

    这样做应该能够解决你遇到的问题。如果问题仍然存在,请尝试检查证书链是否正确,并确保证书是有效的。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
  • 「已注销」 2023-03-19 14:15
    关注

    参考gpt和自己的思路,从你提供的代码中,似乎没有出现明显的错误,但是可以看到在 Java 服务端代码中,SSLContext 初始化时指定的协议为 TLSv1.2,而在 C# 客户端代码中,AuthenticateAsClient 方法指定的协议也为 TLSv1.2。然而,这两者之间通信时,发现无法建立 SSL 握手。这可能是因为它们没有协商出相同的加密套件(cipher suite),从而导致 SSL 握手失败。

    为了解决这个问题,可以尝试在 Java 服务端代码中添加以下行:

    
    System.setProperty("https.cipherSuites", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256");
    
    
    

    这将指定服务端只使用 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 加密套件,与 C# 客户端中的默认套件相同。如果这个加密套件无法使用,则需要根据 C# 客户端中支持的加密套件来修改服务端代码中的 https.cipherSuites 属性值。

    另外,也可以在 C# 客户端代码中显式指定加密套件。在 AuthenticateAsClient 方法中,使用以下代码指定加密套件

    
    sslStream.AuthenticateAsClient("localhost", certCollection, SslProtocols.Tls12, false, new[] { CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 });
    
    
    

    这将仅使用 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 加密套件进行 SSL 握手。

    最后,如果这些方法都无法解决问题,可以尝试使用 Wireshark 等网络抓包工具来捕获 SSL 握手的网络流量,以便进一步分析问题。

    对于Java服务器端的SSL通信问题,您可以尝试通过指定更高级别的加密协议解决。例如,在服务器端SSLContext中使用TLSv1.2作为协议,示例代码如下:

    
    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
    
    
    

    对于C#客户端的SSL通信问题,您可以尝试指定支持的协议和加密算法。例如,以下代码设置支持TLS 1.2并且使用AES256-SHA256加密算法:

    
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
    X509Certificate2 certificate = new X509Certificate2("client.pfx", "password");
    TcpClient client = new TcpClient("serverIP", port);
    SslStream sslStream = new SslStream(client.GetStream(), false, (sender, cert, chain, errors) => true);
    sslStream.AuthenticateAsClient("serverName", new X509Certificate2Collection(certificate), SslProtocols.Tls12, false);
    
    
    

    示例代码中的参数可能需要根据您的实际情况进行修改。

    评论 编辑记录
  • 眉山央央an 2023-03-19 21:11
    关注

    哥哥你这个问题可能是由于客户端和服务端协商的加密算法不一致导致的。您可以尝试更改服务端SSLContext的初始化方式,指定支持的加密协议和密码套件。例如,以下代码将指定只使用TLSv1.2协议和TLS_RSA_WITH_AES_128_CBC_SHA加密套件:

    SSLParameters sslParams = new SSLParameters();
    sslParams.setProtocols(new String[] {"TLSv1.2"});
    sslParams.setCipherSuites(new String[] {"TLS_RSA_WITH_AES_128_CBC_SHA"});
    sslParams.setNeedClientAuth(false);
    sslParams.setWantClientAuth(false);
    
    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
    SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
    SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port);
    sslServerSocket.setEnabledProtocols(sslParams.getProtocols());
    sslServerSocket.setEnabledCipherSuites(sslParams.getCipherSuites());
    

    同样地,您也需要在客户端中指定相同的加密协议和密码套件。在代码中添加以下行,以便将其添加到客户端认证的sslStream中:

    sslStream.SslProtocol = SslProtocols.Tls12;
    sslStream.CipherAlgorithm = CipherAlgorithmType.Aes128;
    sslStream.HashAlgorithm = HashAlgorithmType.Sha1;
    

    这个错误通常意味着客户端和服务器端没有共同的加密套件,因此无法建立安全连接。在您的代码中,可能有以下问题:

    1. 客户端和服务器端使用的 SSL/TLS 协议版本不同,您应该确保两者都使用相同的协议版本。
    1. 客户端和服务器端使用的加密套件不同,您应该检查两者可以使用的加密套件列表,以确保它们具有至少一个相同的套件。
    1. 证书校验未通过,您应该检查证书是否正确,并确认它在双方都被信任。

    请尝试以下步骤:

    1. 检查客户端和服务器端使用的 SSL/TLS 协议版本是否相同。在 C# 中,您可以将 SslProtocols 枚举作为 AuthenticateAsClient 方法的参数传递,例如:sslStream.AuthenticateAsClient("localhost", certCollection, SslProtocols.Tls12, false);
    1. 检查客户端和服务器端使用的加密套件是否相同。在 Java 中,您可以在 SSLContext 初始化时指定需要使用的加密套件,例如:sslContext.setEnabledCipherSuites(new String[] {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"}); 在 C# 中,您可以在创建 SslStream 实例时指定使用的加密套件,例如:SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null, SslProtocols.Tls12, SslStrength.All, true);
    1. 检查证书是否正确,并确认它在双方都被信任。您可以尝试从客户端和服务器端分别访问对方的证书,以确保证书是有效的。例如,在 Java 中,您可以使用以下代码来加载证书并验证其可用性:
    KeyStore ks = KeyStore.getInstance("JKS");
    ks.load(new FileInputStream("E:\\client.jks"), "123456".toCharArray());
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    tmf.init(ks);
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmf.getTrustManagers(), null);
    SSLSocketFactory factory = sslContext.getSocketFactory();
    SSLSocket socket = (SSLSocket) factory.createSocket("localhost", 8080);
    socket.startHandshake();
    

    在 C# 中,您可以使用以下代码加载证书并验证其可用性:

    X509Certificate2 certificate = new X509Certificate2("E:\\client.pfx", "123456");
    X509Chain chain = new X509Chain();
    chain.Build(certificate);
    bool isValid = chain.ChainStatus.Length == 0;
    
    评论 编辑记录
  • OKX安生 2023-03-21 02:11
    关注

    该回答引用于gpt与自己的思路:

    你这个问题可能是由于客户端和服务端协商的加密算法不一致导致的。您可以尝试更改服务端SSLContext的初始化方式,指定支持的加密协议和密码套件。例如,以下代码将指定只使用TLSv1.2协议和TLS_RSA_WITH_AES_128_CBC_SHA加密套件:

    
    
    SSLParameters sslParams = new SSLParameters();
    sslParams.setProtocols(new String[] {"TLSv1.2"});
    sslParams.setCipherSuites(new String[] {"TLS_RSA_WITH_AES_128_CBC_SHA"});
    sslParams.setNeedClientAuth(false);
    sslParams.setWantClientAuth(false);
     
    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
    SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
    SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port);
    sslServerSocket.setEnabledProtocols(sslParams.getProtocols());
    sslServerSocket.setEnabledCipherSuites(sslParams.getCipherSuites());
    
    

    同样地,您也需要在客户端中指定相同的加密协议和密码套件。在代码中添加以下行,以便将其添加到客户端认证的sslStream中:

    sslStream.SslProtocol = SslProtocols.Tls12;
    sslStream.CipherAlgorithm = CipherAlgorithmType.Aes128;
    sslStream.HashAlgorithm = HashAlgorithmType.Sha1;
    
    
    
    

    这个错误通常意味着客户端和服务器端没有共同的加密套件,因此无法建立安全连接。在您的代码中,可能有以下问题:
    客户端和服务器端使用的 SSL/TLS 协议版本不同,您应该确保两者都使用相同的协议版本。
    客户端和服务器端使用的加密套件不同,您应该检查两者可以使用的加密套件列表,以确保它们具有至少一个相同的套件。
    证书校验未通过,您应该检查证书是否正确,并确认它在双方都被信任。

    请尝试以下步骤:
    检查客户端和服务器端使用的 SSL/TLS 协议版本是否相同。在 C# 中,您可以将 SslProtocols 枚举作为 AuthenticateAsClient 方法的参数传递,例如:sslStream.AuthenticateAsClient("localhost", certCollection, SslProtocols.Tls12, false);

    检查客户端和服务器端使用的加密套件是否相同。
    在 Java 中,您可以在 SSLContext 初始化时指定需要使用的加密套件,例如:sslContext.setEnabledCipherSuites(new String[] {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});

    在 C# 中,您可以在创建 SslStream 实例时指定使用的加密套件,例如:SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null, SslProtocols.Tls12, SslStrength.All, true);

    检查证书是否正确,并确认它在双方都被信任。您可以尝试从客户端和服务器端分别访问对方的证书,以确保证书是有效的。

    例如,在 Java 中,您可以使用以下代码来加载证书并验证其可用性:

    KeyStore ks = KeyStore.getInstance("JKS");
    ks.load(new FileInputStream("E:\\client.jks"), "123456".toCharArray());
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    tmf.init(ks);
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmf.getTrustManagers(), null);
    SSLSocketFactory factory = sslContext.getSocketFactory();
    SSLSocket socket = (SSLSocket) factory.createSocket("localhost", 8080);
    socket.startHandshake();
    
    
    
    

    在 C# 中,您可以使用以下代码加载证书并验证其可用性:

    X509Certificate2 certificate = new X509Certificate2("E:\\client.pfx", "123456");
    X509Chain chain = new X509Chain();
    chain.Build(certificate);
    bool isValid = chain.ChainStatus.Length == 0;
    
    
    
    
    评论 编辑记录
  • 追cium 2023-03-19 14:00
    关注

    参考GPT和自己的思路:

    根据您提供的信息,C# 客户端和 Java 服务端之间进行 SSL 通信时出现了问题。具体来说,Java 报错信息为“no cipher suites in common”,而 C# 报错信息为“System.Security.Authentication.AuthenticationException”。这可能是因为客户端和服务端之间没有共同的加密算法或证书。以下是您可以尝试的一些解决方案:

    1. 确保客户端和服务端都支持相同的加密算法(即同一种 TLS 或 SSL 版本)和证书。您可以尝试使用较低的加密算法版本来查看是否存在问题。您还可以运行以下命令以查看客户端和服务端支持的加密算法:
    • Java: System.out.println(Arrays.toString(((SSLSocket) socket).getEnabledCipherSuites()));
    • C#: SslProtocols sslProtocols = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12; Console.WriteLine(string.Join(Environment.NewLine, sslStream.SslProtocol));
    1. 确保证书正确安装并为客户端和服务端都提供了一个副本。您可以尝试重新生成证书并重新安装它们。

    2. 确保客户端和服务端都使用正确的证书。如果证书不正确,则可能会出现无法找到密码、无法解析证书等错误。您可以尝试使用 openssl 等工具来查看证书详细信息。

    3. 尝试在客户端和服务端之间进行简单的非加密通信,以确保基本通信设置正确。

    4. 尝试在客户端和服务端之间进行调试通信,并查看可能有关问题的错误或日志信息。

    希望这些解决方案对解决您的问题有所帮助。如果问题仍然存在,请提供更多详细信息以帮助找到问题。

    评论
  • BitGPT 2023-03-19 14:03
    关注

    该回答引用ChatGPT

    如有疑问,可以回复我!

    错误“no cipher suites in common”表明Java服务器和C#客户端没有共同的密码套件。要解决这个问题,你可以尝试以下几个解决方案:

    1、确保服务器和客户端使用相同的密码套件。你可以在Java服务器代码的SSLSocket上设置允许的密码套件,如下所示:

    String[] enabledCipherSuites = {"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"};
    socket.setEnabledCipherSuites(enabledCipherSuites);
    
    

    同样,在C#客户端代码中,你可以在SslStream上设置允许的密码套件,如下所示:

    sslStream.AuthenticateAsClient("localhost", certCollection, SslProtocols.Tls12, false, enabledCipherSuites);
    
    

    其中enabledCipherSuites是一个包含允许的密码套件的字符串数组。

    2、确保服务器和客户端使用相同的SSL/TLS协议。在你的Java服务器代码中,你已经使用了TLSv1.2协议。确保C#客户端代码中也使用相同的协议。在你的代码中,你已经使用了SslProtocols.Tls12,所以这部分应该没问题。

    3、确保服务器和客户端的证书是正确的并且彼此信任。验证证书链是否完整,确保证书没有过期。你可以尝试使用openssl或其他工具检查证书。

    如果上述方法都无法解决问题,请考虑检查服务器和客户端的日志以获取更详细的信息。为了启用Java的SSL调试日志,你可以在启动Java程序时添加以下JVM参数:

    -Djavax.net.debug=ssl
    
    

    对于C#客户端,你可以尝试在Visual Studio中使用调试模式来检查任何可能的问题。

    评论
  • 蓝白、波罗歌 2023-03-20 09:54
    关注

    以下答案由GPT-3.5大模型与博主波罗歌共同编写:
    这个错误是由于客户端和服务器端不能够协商出一种共同支持的加密套件,导致SSL握手失败。在C#与java间使用SSL通信时,需要确保两端 SSL的协议、加密算法、密钥长度以及证书等的设置是一样的。

    在你的代码中,java端使用的是JKS证书类型,而C#端使用的是PFX证书,这种情况下需要互相转换证书格式,并确保证书的密码一致。

    其中,Java证书转为pfx证书可使用如下命令:

    keytool -importkeystore -srckeystore server.jks -destkeystore server.pfx -srcstoretype jks -deststoretype pkcs12
    

    而PFX证书转为Java证书可使用如下命令:

    keytool -importkeystore -srckeystore client.pfx -destkeystore client.jks -srcstoretype pkcs12 -deststoretype jks
    

    同时,请确保客户端和服务端支持的SSL协议、加密算法和密钥长度是一致的。建议C#端使用TLS1.2协议,并支持ECDHE_RSA加密算法。Java代码中如果想只支持TLSv1.2协议可以使用如下代码:

    sslContext.getInstance("TLSv1.2")
    

    另外,你的C#代码中没有设置远程证书验证的委托,在实际使用时会不安全,建议添加远程证书校验的方法,如:

    private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        if (sslPolicyErrors == SslPolicyErrors.None)
        {
            return true;
        }
        Console.WriteLine("SSL 证书验证失败:" + sslPolicyErrors);
        return false;
    }
    

    并在AuthenticateAsClient时传入此验证方法:

    sslStream.AuthenticateAsClient("localhost", certCollection, SslProtocols.Tls12, false, ValidateServerCertificate);
    

    完整的C#代码如下:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Net.Security;
    using System.Net.Sockets;
    using System.Security.Authentication;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    
    namespace SslTest
    {
        internal class SSLClient
        {
            public static void Main(string[] args)
            {
                int port = 8080;
    
                // 创建 SSL 证书集合
                X509CertificateCollection certCollection = new X509CertificateCollection();
                certCollection.Add(new X509Certificate2("client.pfx", "123456"));
    
                // 创建 SSL 流
                TcpClient client = new TcpClient("localhost", port);
                SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
    
                try
                {
                    // 客户端认证
                    sslStream.AuthenticateAsClient("localhost", certCollection, SslProtocols.Tls12, false, ValidateServerCertificate);
                    Console.WriteLine("客户端已连接服务器");
                }
                catch (AuthenticationException e)
                {
                    Console.WriteLine("Exception: {0}", e.Message);
                    if (e.InnerException != null)
                    {
                        Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                    }
                    Console.WriteLine("Authentication failed - closing the connection.");
                    client.Close();
                    return;
                }
    
                // 向服务器发送消息
                string message = "你好,服务器!";
                byte[] messageBytes = Encoding.UTF8.GetBytes(message);
                sslStream.Write(messageBytes);
                sslStream.Flush();
    
                Console.WriteLine("已向服务器发送消息:" + message);
    
                // 接收服务器的响应消息
                byte[] buffer = new byte[2048];
                int bytesRead;
    
                while ((bytesRead = sslStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    Console.WriteLine("接收到服务器的响应消息:" + response);
                }
    
                // 关闭 SSL 流和客户端 socket
                sslStream.Close();
                client.Close();
            }
    
            private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
            {
                if (sslPolicyErrors == SslPolicyErrors.None)
                {
                    return true;
                }
    
                Console.WriteLine("SSL 证书验证失败:" + sslPolicyErrors);
                return false;
            }
    
        }
    }
    

    完整的Java代码如下:

    import com.google.gson.Gson;
    
    import javax.net.ssl.*;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.security.KeyStore;
    import java.security.Security;
    
    
    public class SSLServer {
        public static void main(String[] args) throws Exception {
    
            // 添加 BouncyCastle 作为安全提供者
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    
            // Set up key manager to do server authentication
            char[] passphrase = "123456".toCharArray();
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(SSLServer.class.getResourceAsStream("server.jks"), passphrase);
    
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, passphrase);
    
            // Set up trust manager to do client authentication
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(ks);
    
            // Set up SSL context
            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
            SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
    
            // Start server
            ServerSocket serverSocket = sslServerSocketFactory.createServerSocket(8080);
    
            System.out.println("Server started on port 8080");
    
            Gson gson = new Gson();
            String message = "接收消息成功";
    
            while (true) {
                // Accept client connections
                SSLSocket socket = (SSLSocket) serverSocket.accept();
                InetAddress address = socket.getInetAddress();
    
                System.out.println("Client connected: " + address.getHostAddress());
    
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
    
                // Receive message from client
                String msg = reader.readLine();
                System.out.println("Message received: " + msg);
    
                // Send message back to client
                writer.println(message);
                writer.flush();
    
                socket.close();
                System.out.println("Client disconnected: " + socket.getInetAddress());
            }
        }
    }
    

    如果我的回答解决了您的问题,请采纳!

    评论
查看更多回答(6条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月27日
  • 已采纳回答 3月24日
  • 创建了问题 3月19日

悬赏问题

  • ¥15 利用加权最小二乘法求亚马逊各类商品的价格指标?怎么求?
  • ¥15 c++ word自动化,为什么可用接口是空的?
  • ¥15 Matlab计算100000*100000的矩阵运算问题:
  • ¥50 VB6.0如何识别粘连的不规则的数字图片验证码
  • ¥16 需要完整的这份订单所有的代码,可以加钱
  • ¥30 写一个带界面控制的机房电脑一键开机关机并且实时监控的软件
  • ¥15 Stata数据分析请教
  • ¥15 请教如何为VS2022搭建 Debug|win32的openCV环境?
  • ¥15 关于#c++#的问题:c++如何使用websocketpp实现websocket接口调用,求示例代码和相关资料
  • ¥15 51单片机的外部中断,按下按键后不能切换到另一个模式