Java开发LDAP Socket服务端可连接但无法收发消息问题求助
核心问题
- LDAP 是基于 ASN.1 BER 编码的二进制传输协议,不是 HTTP 这类以换行符作为分隔的文本协议。你使用
readLine()读取数据流的逻辑完全不匹配:readLine()会一直等待换行符(\n / \r\n)或者流断开才会返回,而正常的 LDAP 报文中不会包含换行符,所以程序会一直卡在读取逻辑,不会打印内容,也不会往下执行返回响应。 - 你当前的服务端逻辑是单次接收连接、读取一次就关闭连接,不符合 LDAP 长连接交互的规则:客户端会在同一个连接上先后发送绑定请求、操作请求,等待服务端逐个返回响应,你直接关闭连接会导致客户端请求直接失败。
修复方案
你需要先按 BER 编码规则读取完整的 LDAP 报文,再给客户端返回符合规范的响应报文,修改后的最简可运行服务端示例如下:
import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Server { private ServerSocket server = null; public Server(int port) { try { server = new ServerSocket(port); System.out.println("Server started"); while (true) { // 循环接受客户端连接 System.out.println("Waiting for a client ..."); Socket socket = server.accept(); System.out.println("Client accepted"); // 新开线程处理单个客户端的所有请求 new Thread(() -> handleClient(socket)).start(); } } catch (IOException i) { System.out.println(i); } } private void handleClient(Socket socket) { try (InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream()) { byte[] buffer = new byte[4096]; while (true) { // 先读取 BER Tag(第一个字节) int tag = in.read(); if (tag == -1) break; // 客户端断开连接 // 读取 BER 长度字段 int len = readBerLength(in); // 读取完整报文内容 int readLen = in.read(buffer, 0, len); // 打印报文十六进制内容 System.out.printf("收到LDAP报文,Tag: 0x%X, 长度: %d, 内容: ", tag, len); for (int i = 0; i < readLen; i++) { System.out.printf("%02X ", buffer[i]); } System.out.println(); // 测试用:返回最简单的绑定成功响应 // 响应报文含义:LDAP消息(0x30) 长度12,消息ID 1,绑定响应(0x61) 成功(0x00) byte[] bindResp = new byte[]{0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00}; out.write(bindResp); out.flush(); } } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println("客户端连接关闭"); } } // 读取BER编码的长度字段 private int readBerLength(InputStream in) throws IOException { int b = in.read(); if (b == -1) throw new EOFException(); if ((b & 0x80) == 0) { return b; } int lenBytes = b & 0x7F; int len = 0; for (int i = 0; i < lenBytes; i++) { b = in.read(); if (b == -1) throw new EOFException(); len = (len << 8) | b; } return len; } public static void main(String args[]) { new Server(10389); } }
如果你需要完整处理各种 LDAP 操作请求,建议直接使用成熟的 LDAP 编解码库,不用自己手动实现 ASN.1 解析逻辑,降低开发成本。
内容的提问来源于stack exchange,提问作者notFound
相关产品推荐
相关产品推荐

