|
@@ -0,0 +1,221 @@
|
|
|
+package com.pig4cloud.pig.statistics.socket;
|
|
|
+
|
|
|
+import java.io.*;
|
|
|
+import java.net.*;
|
|
|
+import java.nio.file.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * TCP客户端测试类,用于测试服务器功能
|
|
|
+ * 支持发送文本消息和图片文件
|
|
|
+ */
|
|
|
+public class TcpClient {
|
|
|
+ // 协议定义,与服务器保持一致
|
|
|
+ private static final byte PACKET_HEADER = 0x2;
|
|
|
+ private static final byte PACKET_TAIL = 0x3;
|
|
|
+ private static final byte TYPE_TEXT = 0x01;
|
|
|
+ private static final byte TYPE_IMAGE = 0x02;
|
|
|
+
|
|
|
+ private String serverHost;
|
|
|
+ private int serverPort;
|
|
|
+ private Socket socket;
|
|
|
+ private InputStream in;
|
|
|
+ private OutputStream out;
|
|
|
+
|
|
|
+ public TcpClient(String serverHost, int serverPort) {
|
|
|
+ this.serverHost = serverHost;
|
|
|
+ this.serverPort = serverPort;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 连接到服务器
|
|
|
+ */
|
|
|
+ public void connect() throws IOException {
|
|
|
+ socket = new Socket(serverHost, serverPort);
|
|
|
+ in = socket.getInputStream();
|
|
|
+ out = socket.getOutputStream();
|
|
|
+ System.out.println("已连接到服务器: " + serverHost + ":" + serverPort);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送文本消息到服务器
|
|
|
+ */
|
|
|
+ public String sendText(String text) throws IOException {
|
|
|
+ if (socket == null || socket.isClosed()) {
|
|
|
+ throw new IOException("未连接到服务器,请先调用connect()方法");
|
|
|
+ }
|
|
|
+
|
|
|
+ byte[] data = text.getBytes("UTF-8");
|
|
|
+ sendPacket(TYPE_TEXT, data);
|
|
|
+ return receiveResponse();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送图片文件到服务器
|
|
|
+ */
|
|
|
+ public String sendImage(String imageFilePath) throws IOException {
|
|
|
+ if (socket == null || socket.isClosed()) {
|
|
|
+ throw new IOException("未连接到服务器,请先调用connect()方法");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 读取图片文件
|
|
|
+ byte[] imageData = Files.readAllBytes(Paths.get(imageFilePath));
|
|
|
+ sendPacket(TYPE_IMAGE, imageData);
|
|
|
+ return receiveResponse();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 按照协议格式发送数据包
|
|
|
+ */
|
|
|
+ private void sendPacket(int type, byte[] data) throws IOException {
|
|
|
+ ByteArrayOutputStream packetBuffer = new ByteArrayOutputStream();
|
|
|
+
|
|
|
+ // 写入包头
|
|
|
+ packetBuffer.write(PACKET_HEADER);
|
|
|
+
|
|
|
+ // 写入数据类型
|
|
|
+ packetBuffer.write(type);
|
|
|
+
|
|
|
+ // 写入数据长度(4字节,大端模式)
|
|
|
+ packetBuffer.write((data.length >> 24) & 0xFF);
|
|
|
+ packetBuffer.write((data.length >> 16) & 0xFF);
|
|
|
+ packetBuffer.write((data.length >> 8) & 0xFF);
|
|
|
+ packetBuffer.write(data.length & 0xFF);
|
|
|
+
|
|
|
+ // 写入数据内容
|
|
|
+ packetBuffer.write(data);
|
|
|
+
|
|
|
+ // 写入包尾
|
|
|
+ packetBuffer.write(PACKET_TAIL);
|
|
|
+
|
|
|
+ // 发送数据包
|
|
|
+ out.write(packetBuffer.toByteArray());
|
|
|
+ out.flush();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接收服务器响应
|
|
|
+ */
|
|
|
+ private String receiveResponse() throws IOException {
|
|
|
+ // 解析服务器响应的数据包
|
|
|
+ ByteArrayOutputStream packetBuffer = new ByteArrayOutputStream();
|
|
|
+ boolean inPacket = false;
|
|
|
+ int dataType = -1;
|
|
|
+ byte[] lengthBytes = new byte[4];
|
|
|
+ int lengthIndex = 0;
|
|
|
+ int contentLength = -1;
|
|
|
+ ByteArrayOutputStream contentBuffer = new ByteArrayOutputStream();
|
|
|
+
|
|
|
+ int b;
|
|
|
+ while ((b = in.read()) != -1) {
|
|
|
+ byte currentByte = (byte) b;
|
|
|
+
|
|
|
+ // 处理包头
|
|
|
+ if (!inPacket && currentByte == PACKET_HEADER) {
|
|
|
+ inPacket = true;
|
|
|
+ packetBuffer.reset();
|
|
|
+ packetBuffer.write(currentByte);
|
|
|
+ lengthIndex = 0;
|
|
|
+ contentLength = -1;
|
|
|
+ contentBuffer.reset();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理包内数据
|
|
|
+ if (inPacket) {
|
|
|
+ packetBuffer.write(currentByte);
|
|
|
+
|
|
|
+ // 读取数据类型
|
|
|
+ if (dataType == -1) {
|
|
|
+ dataType = currentByte & 0xFF;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 读取数据长度(4字节)
|
|
|
+ if (contentLength == -1) {
|
|
|
+ lengthBytes[lengthIndex++] = currentByte;
|
|
|
+ if (lengthIndex == 4) {
|
|
|
+ // 转换4字节为整数(大端模式)
|
|
|
+ contentLength = ((lengthBytes[0] & 0xFF) << 24) |
|
|
|
+ ((lengthBytes[1] & 0xFF) << 16) |
|
|
|
+ ((lengthBytes[2] & 0xFF) << 8) |
|
|
|
+ (lengthBytes[3] & 0xFF);
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 读取数据内容
|
|
|
+ if (contentBuffer.size() < contentLength) {
|
|
|
+ contentBuffer.write(currentByte);
|
|
|
+
|
|
|
+ // 检查是否已读取所有内容
|
|
|
+ if (contentBuffer.size() == contentLength) {
|
|
|
+ // 接下来应该是包尾
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 检查包尾
|
|
|
+ if (currentByte == PACKET_TAIL) {
|
|
|
+ // 完整包接收完成,返回内容
|
|
|
+ return new String(contentBuffer.toByteArray(), "UTF-8");
|
|
|
+ } else {
|
|
|
+ // 包尾不正确,视为无效包
|
|
|
+ throw new IOException("收到无效的数据包,包尾不正确");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new IOException("与服务器的连接已关闭");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭与服务器的连接
|
|
|
+ */
|
|
|
+ public void disconnect() {
|
|
|
+ try {
|
|
|
+ if (in != null) in.close();
|
|
|
+ if (out != null) out.close();
|
|
|
+ if (socket != null && !socket.isClosed()) {
|
|
|
+ socket.close();
|
|
|
+ System.out.println("已断开与服务器的连接");
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ System.err.println("关闭连接时发生错误: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试方法
|
|
|
+ */
|
|
|
+ public static void main(String[] args) {
|
|
|
+ // 服务器地址和端口
|
|
|
+ String host = "localhost";
|
|
|
+ int port = 8888;
|
|
|
+
|
|
|
+ TcpClient client = new TcpClient(host, port);
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 连接服务器
|
|
|
+ client.connect();
|
|
|
+
|
|
|
+ // 测试发送文本
|
|
|
+ String text = "Hello, TCP Server!";
|
|
|
+ System.out.println("发送文本: " + text);
|
|
|
+ String textResponse = client.sendText(text);
|
|
|
+ System.out.println("服务器响应: " + textResponse);
|
|
|
+
|
|
|
+ // 测试发送图片(请替换为实际的图片路径)
|
|
|
+ String imagePath = "C:\\Users\\L\\Desktop\\素材\\image16.png"; // 测试图片路径
|
|
|
+ System.out.println("发送图片: " + imagePath);
|
|
|
+ String imageResponse = client.sendImage(imagePath);
|
|
|
+ System.out.println("服务器响应: " + imageResponse);
|
|
|
+
|
|
|
+ } catch (IOException e) {
|
|
|
+ System.err.println("客户端错误: " + e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ } finally {
|
|
|
+ // 断开连接
|
|
|
+ client.disconnect();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|