##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. (4)Microsoft office Word 2013版本操作入门_插入图片及图片的排版

    1.word中插入图片和文绕图 1.1插入图片 :点击[插入]-->[图片] 或者 [联机图片]从网上选择. 1.2文字环绕: [格式] --->点击[位置]   .[自动换行]  进行图 ...

  2. java回调函数学习

    前不久学习了代理模式,其中有一个核心之一是Proxy.newProxyInstance();这里有三个参数, loader:目标对象的类加载器 interfaces:目标对象实现的所有接口组成的数组 ...

  3. js正则表达式 URL格式匹配详解

    0.URL格式 protocol :// hostname[:port] / path / [;parameters][?query]#fragment [;parameters]没见过 这里就不做相 ...

  4. mac gulp: command not found

    mac下执行gulp的时候报错:gulp: command not found 1.查看npm的安装目录 npm root 2.如果不是/usr/local , 说明未全局安装,执行 sudo npm ...

  5. jQuery 练习:取出数组字典的值, 静态对话框, clone方法应用

    jQuery 中文API文档 http://jquery.cuishifeng.cn/ jQuery 取出数组字典的值 <head> <meta charset="UTF- ...

  6. Django的下载安装以及实现一个简单示例

    一.Django下载安装 Django下载链接 1. 下载Django: pip3 install django==1.11.9    (大的版本1.11不要错) 2.创建一个django proje ...

  7. DEM山体阴影原理以及算法具体解释

    山体阴影原理以及算法具体解释 山体阴影基本原理: 山体阴影是假想一个光源在某个方向和某个太阳高度的模拟下.用过临近像元的计算来生成一副0-255的灰度图. 一.山体阴影的主要參数: 1.  太阳光线的 ...

  8. iOS中时间与时间戳的相互转化

    //获取当前系统时间的时间戳 #pragma mark - 获取当前时间的 时间戳 +(NSInteger)getNowTimestamp{ NSDateFormatter *formatter = ...

  9. Java map 详解

    Map 提供了一个更通用的元素存储方法.Map 集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值. 初始化一个集合:  Map<String, String> map = ...

  10. 使用Visual Studio Team Services持续集成(二)——为构建定义属性

    使用Visual Studio Team Services持续集成(二)--为构建定义属性 1.从VSTS帐户进入到Build 2.编辑构建定义并单击Options Description:如果这里明 ...