基於原始 Socket 與 ServerSocket 實現字節級數據傳輸,服務端使用 BufferedInputStream + DataInputStream 讀取,客戶端使用 DataOutputStream 發送,含十六進制調試輸出工具方法。
public class TalkServer4Byte {
private ServerSocket server;
private int port = 5020;
public TalkServer4Byte() {
try { server = new ServerSocket(port); }
catch (IOException e) { e.printStackTrace(); }
}
public void talk() {
System.out.println("監聽端口: " + port);
while (true) {
try (Socket socket = server.accept()) {
System.out.println("客戶端連接: " + socket.getRemoteSocketAddress());
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
DataInputStream dis = new DataInputStream(bis);
byte[] buffer = new byte[1];
StringBuilder hexLog = new StringBuilder();
while (dis.read(buffer) != -1) {
hexLog.append(bytesToHexString(buffer)).append(" ");
if (dis.available() == 0) { // 一個請求讀取完畢
doSomething(hexLog.toString());
hexLog.setLength(0);
}
}
} catch (IOException e) { e.printStackTrace(); }
}
}
private static void doSomething(String hex) {
System.out.println("收到數據: " + hex);
}
// 字節數組轉十六進制字符串 (大寫、雙位補零)
public static String bytesToHexString(byte[] src) {
StringBuilder sb = new StringBuilder();
for (byte b : src) {
String hv = Integer.toHexString(b & 0xFF);
if (hv.length() < 2) sb.append('0');
sb.append(hv.toUpperCase());
}
return sb.toString();
}
public static void main(String[] args) {
new TalkServer4Byte().talk();
}
}
public class TalkClient4Byte {
private Socket socket;
public TalkClient4Byte() {
try {
socket = new Socket();
socket.connect(new InetSocketAddress("127.0.0.1", 5020), 1000);
} catch (IOException e) { e.printStackTrace(); }
}
public void talk() {
try (DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
DataInputStream dis = new DataInputStream(System.in)) {
byte[] buffer = new byte[1];
while (dis.read(buffer) != -1) {
dos.write(buffer); // 逐字節發送
}
dos.flush();
} catch (IOException e) { e.printStackTrace(); }
}
public static void main(String[] args) {
new TalkClient4Byte().talk();
}
}
InputStream/OutputStream 體系,適合二進制協議/文件傳輸;文本協議建議用 Reader/Writer 或 BufferedReader/PrintWriterdis.available() == 0 判斷單次請求結束,適用於定長/無分隔符協議;生產環境建議使用長度前綴或分隔符幂等解析bytesToHexString 將不可見字節可視化,便於協議調試try-with-resources 自動關閉 Socket/流,防止洩漏