##socket 丢包粘包解决方式

采用固定头部长度(一般为4个字节),包头保存的是包体的长度

header+body

包头+包体

下面的例子不是按照上图中规定的格式编写的,但是思路都是一样的,先读出一个包头,得到包体的长度,解析出包体

public class SocketServer {
public static void main(String args[]) {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress());
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 = ;// 包头长度
private Socket socket;
private volatile byte[] bytes = new byte[]; 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 = ;
for (i = ; 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 = ;
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 < ) {
continue;
}
bytes = mergebyte(bytes, head, , couter);
if (couter < PACKET_HEAD_LENGTH) {
continue;
}
}
} // 取出包体长度
byte[] temp = new byte[];
temp = mergebyte(temp, bytes, , 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 < ) {
continue;
}
bytes = mergebyte(bytes, body, , couter);
if (couter < body.length) {
continue;
}
} //把包体的内容读取出来
byte[] body = new byte[];
body = mergebyte(body, bytes, PACKET_HEAD_LENGTH, bytes.length);
count++;
System.out.println("server receive body: " + count + new String(body));
//为读取下一个包将数组长度重置为空数组,长度为0
bytes = new byte[];
} 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());
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 = ; i < ; 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 = ;
for (i = ; i < headbytes.length; i++) {// 包头
bytes[i] = headbytes[i];
}
for (int j = i, k = ; 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();
System.out.println(byteArrayToInt(res)); } public static byte[] intToByteArray(int i) {
byte[] result = new byte[];
// 由高位到低位
result[] = (byte) ((i >> ) & 0xFF);
result[] = (byte) ((i >> ) & 0xFF);
result[] = (byte) ((i >> ) & 0xFF);
result[] = (byte) (i & 0xFF);
return result;
} public static int byteArrayToInt(byte[] bytes) {
int value = ;
// 由高位到低位
for (int i = ; i < ; i++) {
int shift = ( - - i) * ;
value += (bytes[i] & 0x000000FF) << shift;// 往高位游
}
return value;
}
}

转自: https://blog.csdn.net/nongfuyumin/article/details/78298380?utm_source=blogxgwz5

socket编程解决粘包和丢包问题的更多相关文章

  1. python/socket编程之粘包

    python/socket编程之粘包 粘包 只有TCP有粘包现象,UDP永远不会粘包. 首先需要掌握一个socket收发消息的原理 发送端可以是1k,1k的发送数据而接受端的应用程序可以2k,2k的提 ...

  2. VS2015编译FFMPEG,修改FFmpeg缓冲区大小解决实时流解码丢包问题,FFmpeg错误rtsp流地址卡死的问题,设置超时

    之前尝试过很多网上利用Windows编译FFmpeg的文章,都没有办法编译X64位的FFmpeg,有些教程中有专门提到编译64位的FFmpeg需要下载mingw-w64-install,但是编译的过程 ...

  3. 嵌入式开发之UDP 丢包--- UDP 丢包控制方法

    0. 发送端可以,发送五次左右,再Sleep 1.调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来的包可能丢失.对于这种情况可以修改接收 ...

  4. socket编程 TCP 粘包和半包 的问题及解决办法

    一般在socket处理大数据量传输的时候会产生粘包和半包问题,有的时候tcp为了提高效率会缓冲N个包后再一起发出去,这个与缓存和网络有关系. 粘包 为x.5个包 半包 为0.5个包 由于网络原因 一次 ...

  5. Socket编程--TCP粘包问题

    TCP是个流协议,它存在粘包问题 产生粘包的原因是: TCP所传输的报文段有MSS的限制,如果套接字缓冲区的大小大于MSS,也会导致消息的分割发送. 由于链路层最大发送单元MTU,在IP层会进行数据的 ...

  6. day34 基于TCP和UDP的套接字方法 粘包问题 丢包问题

    TCP 基于流的协议 又叫可靠性传输协议 通过三次握手 四次挥手 来保证数据传输完毕 缺点效率低 正因为是基于流的协议 所以会出现粘包问题粘包问题:原因一:是应为数据是先发送给操作系统,在操作系统中有 ...

  7. socket之解决粘包方法

    low方法 import socket,subprocess ip_port=('127.0.0.1',8080) s=socket.socket(socket.AF_INET,socket.SOCK ...

  8. C#中Socket编程解决应用程序直接的通信

    using System;using System.Collections.Generic;using System.Linq;using System.Text; using System.Net; ...

  9. UDP丢包和无序 问题的解决方法

    最近在做一个项目,在这之前,做了个验证程序. 发现客户端连续发来1000个1024字节的包,服务器端出现了丢包现象. 纠其原因,是服务端在还未完全处理掉数据,客户端已经数据发送完毕且关闭了. 我用过s ...

随机推荐

  1. 最长滑道问题(非递归,C++)

    这是爱奇艺的一道算法题. 题目描述请参考博客http://blog.csdn.net/sinat_30186009/article/details/52356053,在此表示感谢. 基本思路参考了以上 ...

  2. 【Mybatis】MyBatis调用带有返回结果、output参数的存储过程上与ibatis的区别

    用过mybatis的应该都知道它是ibatis被Google收购后重新命名的一个工程,因此也做了大量升级.本文就来介绍下两者在调用存储过程上的一点区别,ibatis有一个专门的标签<proced ...

  3. Java中的匿名内部类及内部类的二三事

    匿名内部类适合创建那些只需要使用一次的类,它的语法有些奇怪,创建匿名内部类会立即创建一个该类的实例,这个类定义立即消失,且不能重复使用. 定义匿名类的格式如下: new 实现接口() |父类构造器(实 ...

  4. HTML标签笔记

    换行符:<br/> 首部: <!DOCTYPE>: 说明html文档使用的标准, 在HTML5中仅为 <!DOCTYPE html>1.头标签 <head&g ...

  5. Django之模板

    Django模板系统 官方文档 常用语法 Django模板中只需要记两种特殊符号: {{  }}和 {% %} {{ }}表示变量,在模板渲染的时候替换成值,{% %}表示逻辑相关的操作. 变量 {{ ...

  6. js 格式化数字(每三位加逗号)

    // 方法一 unction toThousands(num) { var result = [ ], counter = 0; num = (num || 0).toString().split(' ...

  7. GitHub for Windows离线安装包

    国内安装github客户端,真的很痛!! 偶然找到了离线安装包,感谢作者的资源分享!!! 地址:http://download.csdn.net/download/lyg468088/8723039? ...

  8. BZOJ 1022: [SHOI2008]小约翰的游戏John (Anti-nim)

    Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3134  Solved: 2003[Submit][Status][Discuss] Descripti ...

  9. div中img依据不同分辨率居中显示,超出部分隐藏

    在做banner居中时 碰到的问题,知道可以用背景图实现居中显示,但是内心是想深究下的,故找到几种办法收集一下,后面两种真的是奇技淫巧 来着下面两处 https://www.zhihu.com/que ...

  10. TFS 2017 持续集成速记

    VS2017许多激动人 心的功能,升级!   TFS2017也升级,不支持SQL2012,升级!不过貌似开发版不能升级,好吧,开发版升2014企业版! 2017据说不支持XAML生成了,但后台菜单中还 ...