java socket编程解决粘包和丢包问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java socket编程解决粘包和丢包问题相关的知识,希望对你有一定的参考价值。
##socket 丢包粘包解决方式
采用固定头部长度(一般为4个字节),包头保存的是包体的长度
header+body
包头+包体
思路是:先读出一个包头,得到包体的长度,解析出包体
public class SocketServer { public static void main(String args[]) { ServerSocket serverSocket; try { serverSocket = new ServerSocket(); serverSocket.bind(new InetSocketAddress(8089)); System.out.println("启动服务端~"); while (true) { Socket socket = serverSocket.accept(); new ReceiveThread(socket).start(); } } catch (IOException e) { e.printStackTrace(); } } static class ReceiveThread extends Thread { public static final int PACKET_HEAD_LENGTH = 4;// 包头长度 private Socket socket; private volatile byte[] bytes = new byte[0]; public ReceiveThread(Socket socket) { this.socket = socket; } //将b数组 下标从begin到end-1的值追加到a数组的后面,并返回 public byte[] mergebyte(byte[] a, byte[] b, int begin, int end) { byte[] add = new byte[a.length + end - begin]; int i = 0; for (i = 0; i < a.length; i++) { add[i] = a[i]; } for (int k = begin; k < end; k++, i++) { add[i] = b[k]; } return add; } @Override public void run() { int count = 0; while (true) { try { InputStream reader = socket.getInputStream(); { //这里可以保证正好读取到4个字节的包头 if (bytes.length < PACKET_HEAD_LENGTH) { //【第一次进来,或者经过一次循环bytes的长度被置为0】 byte[] head = new byte[PACKET_HEAD_LENGTH - bytes.length]; int couter = reader.read(head); if (couter < 0) { continue; } bytes = mergebyte(bytes, head, 0, couter); if (couter < PACKET_HEAD_LENGTH) { continue; } } } // 取出包体长度 byte[] temp = new byte[0]; temp = mergebyte(temp, bytes, 0, PACKET_HEAD_LENGTH); int bodylength = ByteUtil.byteArrayToInt(temp);// 包体长度 //完整读取一个包 if (bytes.length < bodylength + PACKET_HEAD_LENGTH) {// 不够一个包 byte[] body = new byte[bodylength + PACKET_HEAD_LENGTH - bytes.length];// 剩下应该读的字节(凑一个包) int couter = reader.read(body); if (couter < 0) { continue; } bytes = mergebyte(bytes, body, 0, couter); if (couter < body.length) { continue; } } //把包体的内容读取出来 byte[] body = new byte[0]; body = mergebyte(body, bytes, PACKET_HEAD_LENGTH, bytes.length); count++; System.out.println("server receive body: " + count + new String(body)); //为读取下一个包将数组长度重置为空数组,长度为0 bytes = new byte[0]; } catch (Exception e) { e.printStackTrace(); } } } } }
public class ClientSocket { public static void main(String args[]) throws IOException { System.out.println("启动客户端~"); Socket clientSocket = new Socket(); clientSocket.connect(new InetSocketAddress(8089)); new SendThread(clientSocket).start(); } static class SendThread extends Thread { Socket socket; public SendThread(Socket socket) { this.socket = socket; } @Override public void run() { String reqMessage = "HelloWorl ! from clientsocket this is test half packages!"; for (int i = 0; i < 100; i++) { sendPacket(reqMessage+ "u "+ i); } if (socket != null) { try { socket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void sendPacket(String message) { byte[] contentBytes = message.getBytes();// 包体内容 int contentlength = contentBytes.length;// 包体长度 byte[] headbytes = ByteUtil.intToByteArray(contentlength);// 包头字节数组 byte[] bytes = new byte[headbytes.length + contentlength];// 包=包头+包体 int i = 0; for (i = 0; i < headbytes.length; i++) {// 包头 bytes[i] = headbytes[i]; } for (int j = i, k = 0; k < contentlength; k++, j++) {// 包体 bytes[j] = contentBytes[k]; } try { OutputStream writer = socket.getOutputStream(); writer.write(bytes); writer.flush(); } catch (IOException e) { e.printStackTrace(); } } } }
public class ByteUtil { public static void main(String[] args) { byte[] res = intToByteArray(10); System.out.println(byteArrayToInt(res)); } public static byte[] intToByteArray(int i) { byte[] result = new byte[4]; // 由高位到低位 result[0] = (byte) ((i >> 24) & 0xFF); result[1] = (byte) ((i >> 16) & 0xFF); result[2] = (byte) ((i >> 8) & 0xFF); result[3] = (byte) (i & 0xFF); return result; } public static int byteArrayToInt(byte[] bytes) { int value = 0; // 由高位到低位 for (int i = 0; i < 4; i++) { int shift = (4 - 1 - i) * 8; value += (bytes[i] & 0x000000FF) << shift;// 往高位游 } return value; } }
转自: https://blog.csdn.net/nongfuyumin/article/details/78298380?utm_source=blogxgwz5
以上是关于java socket编程解决粘包和丢包问题的主要内容,如果未能解决你的问题,请参考以下文章