java实现TCP客户端,接收服务端固定头尾的包

java实现TCP客户端,连接成功后自动接收服务端的数据,数据包以AABB开头CCDD结尾
支持断开重连

package com.data.thread;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import org.apache.log4j.Logger;

/**
 * socket线程,客户端接收服务端数据,包以AABB开头CCDD结尾
 *
 * @author ls
 */
public class SocketThread extends Thread {

    Logger logger = Logger.getLogger(SocketThread1.class.getName());
    public boolean isRun = false;
    public boolean isWork = false;

    @Override
    public void run() {
        while (isRun) {
            try {
                sleep(1000L);
            } catch (InterruptedException ex) {
                return;
            }

            String hostname = "127.0.0.1"; // 服务器的地址
            int port = 9090; // 服务器的端口号
            InputStream inputStream = null;
            DataInputStream dataInputStream = null;
            Socket socket = null;
            BufferedInputStream in = null;
            try {
                socket = new Socket(hostname, port);
                socket.setSoTimeout(60000);
                in = new BufferedInputStream(socket.getInputStream());

                byte[] buffer = new byte[4096]; // 较大的缓冲区以减少读取次数  
                byte[] packetBuilder = new byte[0]; // 用于构建当前数据包的缓冲区  
                
                while (isWork) {
                    int bytesRead = in.read(buffer);
                    if (bytesRead == -1) {
                        break; // 远程主机已关闭连接  
                    }

                    // 将新读取的数据添加到packetBuilder中  
                    byte[] tempPacket = new byte[packetBuilder.length + bytesRead];
                    System.arraycopy(packetBuilder, 0, tempPacket, 0, packetBuilder.length);
                    System.arraycopy(buffer, 0, tempPacket, packetBuilder.length, bytesRead);
                    packetBuilder = tempPacket;

                    // 查找数据包  
                    int startIndex = -1;
                    int endIndex = -1;

                    // 查找开始标记(AABB)  
                    for (int i = 0; i <= packetBuilder.length - 4; i++) {
                        if (packetBuilder[i] == (byte) 0xAA && packetBuilder[i + 1] == (byte) 0xBB) {
                            startIndex = i;
                            break;
                        }
                    }

                    // 如果找到了开始标记,则查找结束标记(CCDD)  
                    if (startIndex != -1) {
                        for (int i = startIndex + 2; i <= packetBuilder.length - 2; i++) {
                            if (packetBuilder[i] == (byte) 0xCC && packetBuilder[i + 1] == (byte) 0xDD) {
                                endIndex = i + 1; // 包括结束标记  
                                break;
                            }
                        }
                    }

                    // 如果找到了完整的数据包,则处理它
                    if (startIndex != -1 && endIndex != -1) {
                        byte[] packet = new byte[endIndex - startIndex + 1];
                        System.arraycopy(packetBuilder, startIndex, packet, 0, packet.length);
                        logger.info("Received packet: " + bytesToHex(packet));
                        
                        //todo:将数据放入缓存,用于数据处理
                        
                        // 移除已处理的数据包,只保留剩余的数据
                        if (endIndex < packetBuilder.length) {
                            // endIndex 之后的长度是剩余数据的长度
                            int remainingLength = packetBuilder.length - endIndex;
                            // 如果剩余长度大于0,则创建新的数组并复制剩余数据
                            if (remainingLength > 0) {
                                byte[] newPacketBuilder = new byte[remainingLength];
                                System.arraycopy(packetBuilder, endIndex, newPacketBuilder, 0, remainingLength);
                                packetBuilder = newPacketBuilder;
                            } else {
                                // 如果没有剩余数据,则清空packetBuilder
                                packetBuilder = new byte[0];
                            }
                        } else {
                            // 如果endIndex正好是packetBuilder的末尾,那么也没有剩余数据
                            packetBuilder = new byte[0];
                        }
                    }
                }

            } catch (IOException e) {
                logger.error("socket连接失败:" + e);
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException ex) {
                        logger.error(ex);
                    }
                }
                if (dataInputStream != null) {
                    try {
                        dataInputStream.close();
                    } catch (IOException ex) {
                        logger.error(ex);
                    }
                }
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (IOException ex) {
                        logger.error(ex);
                    }
                }
            }
        }
    }

    // 字节数组转换为十六进制字符串  
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString();
    }

    /**
     * 停止采集
     */
    public void stopCol() {
        isRun = false;
        isWork = false;
        this.interrupt();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值