需求:在本地实现java的文字聊天功能。编写两个java对象,一个对象代表服务器,一个对象代表客端,一个代表客户端。客户端输入文字,服务器端接收并响应结果给客户端。

前置条件:首先生成密钥库和证书

# 生成服务器密钥库和自签名证书
keytool -genkeypair -alias server -keyalg RSA -keysize 2048 -storetype JKS -keystore server.keystore -validity 365 -storepass serverpass -keypass serverpass -dname "CN=localhost, OU=Example, O=Example, L=City, ST=State, C=US"

# 导出服务器证书
keytool -exportcert -alias server -keystore server.keystore -file server.crt -storepass serverpass

# 生成客户端信任库并导入服务器证书
keytool -importcert -alias server -file server.crt -keystore client.truststore -storepass clientpass -noprompt

服务器端口代码如下:

package com.example.demo.demos;

import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;

public class Server {
    private static int requestCount = 0; // 计数器记录请求次数

    public static void main(String[] args) {
        try {
            // 加载服务器密钥库(包含私钥和证书)
            KeyStore keyStore = KeyStore.getInstance("JKS");
            keyStore.load(new FileInputStream("server.keystore"), "serverpass".toCharArray());

            // 创建密钥管理器工厂
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(keyStore, "serverpass".toCharArray());

            // 创建SSL上下文并初始化
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(kmf.getKeyManagers(), null, null);

            // 创建SSL服务器套接字工厂
            SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();

            // 创建SSL服务器套接字并绑定端口
            SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(8443);

            // 启用所有支持的密码套件和协议
            sslServerSocket.setEnabledCipherSuites(sslServerSocket.getSupportedCipherSuites());
            sslServerSocket.setEnabledProtocols(sslServerSocket.getSupportedProtocols());

            System.out.println("服务器已启动,等待客户端连接...");

            // 接受客户端连接
            SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();

            // 处理客户端请求
            try (BufferedReader in = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
                 PrintWriter out = new PrintWriter(sslSocket.getOutputStream(), true)) {

                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    requestCount++; // 每次请求计数器+1
                    String response = String.format("第%d次返回结果:%s", requestCount, inputLine); // 格式化响应内容
                    System.out.println("客户端消息: " + inputLine);
                    out.println(response); // 发送格式化后的响应
                }
            }

            sslSocket.close();
            sslServerSocket.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

客户端代码:

package com.example.demo.demos;

import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;

public class Client {
    public static void main(String[] args) {
        try {
            // 加载客户端信任库(包含服务器证书)
            KeyStore trustStore = KeyStore.getInstance("JKS");
            trustStore.load(new FileInputStream("client.truststore"), "clientpass".toCharArray());

            // 创建信任管理器工厂
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(trustStore);

            // 创建SSL上下文并初始化
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), null);

            // 创建SSL套接字工厂
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            // 创建SSL套接字并连接到服务器
            SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket("localhost", 8443);

            // 启用所有支持的密码套件和协议
            sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
            sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols());

            // 向服务器发送消息
            try (PrintWriter out = new PrintWriter(sslSocket.getOutputStream(), true);

                 BufferedReader in = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
                 BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) {
                 System.out.println("请输入内容:");
                String userInput;
                while ((userInput = stdIn.readLine()) != null) {
                    out.println(userInput);
                    System.out.println("服务器返回: " + in.readLine());
                    System.out.println("请继续输入内容:");

                }
            }

            sslSocket.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

关键配置说明

  1. 服务器配置

    • 使用server.keystore存储服务器私钥和证书
    • 通过KeyManagerFactory加载服务器密钥库
    • 服务器使用默认信任库验证客户端证书(如果需要双向认证)
  2. 客户端配置

    • 使用client.truststore存储信任的服务器证书
    • 通过TrustManagerFactory加载客户端信任库
    • 客户端通过SSLContext初始化自定义信任管理器

结果:客户端多次输入,服务器均正常返回。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐