socket编程解决粘包和丢包问题
##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编程解决粘包和丢包问题的更多相关文章
- python/socket编程之粘包
python/socket编程之粘包 粘包 只有TCP有粘包现象,UDP永远不会粘包. 首先需要掌握一个socket收发消息的原理 发送端可以是1k,1k的发送数据而接受端的应用程序可以2k,2k的提 ...
- VS2015编译FFMPEG,修改FFmpeg缓冲区大小解决实时流解码丢包问题,FFmpeg错误rtsp流地址卡死的问题,设置超时
之前尝试过很多网上利用Windows编译FFmpeg的文章,都没有办法编译X64位的FFmpeg,有些教程中有专门提到编译64位的FFmpeg需要下载mingw-w64-install,但是编译的过程 ...
- 嵌入式开发之UDP 丢包--- UDP 丢包控制方法
0. 发送端可以,发送五次左右,再Sleep 1.调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来的包可能丢失.对于这种情况可以修改接收 ...
- socket编程 TCP 粘包和半包 的问题及解决办法
一般在socket处理大数据量传输的时候会产生粘包和半包问题,有的时候tcp为了提高效率会缓冲N个包后再一起发出去,这个与缓存和网络有关系. 粘包 为x.5个包 半包 为0.5个包 由于网络原因 一次 ...
- Socket编程--TCP粘包问题
TCP是个流协议,它存在粘包问题 产生粘包的原因是: TCP所传输的报文段有MSS的限制,如果套接字缓冲区的大小大于MSS,也会导致消息的分割发送. 由于链路层最大发送单元MTU,在IP层会进行数据的 ...
- day34 基于TCP和UDP的套接字方法 粘包问题 丢包问题
TCP 基于流的协议 又叫可靠性传输协议 通过三次握手 四次挥手 来保证数据传输完毕 缺点效率低 正因为是基于流的协议 所以会出现粘包问题粘包问题:原因一:是应为数据是先发送给操作系统,在操作系统中有 ...
- socket之解决粘包方法
low方法 import socket,subprocess ip_port=('127.0.0.1',8080) s=socket.socket(socket.AF_INET,socket.SOCK ...
- C#中Socket编程解决应用程序直接的通信
using System;using System.Collections.Generic;using System.Linq;using System.Text; using System.Net; ...
- UDP丢包和无序 问题的解决方法
最近在做一个项目,在这之前,做了个验证程序. 发现客户端连续发来1000个1024字节的包,服务器端出现了丢包现象. 纠其原因,是服务端在还未完全处理掉数据,客户端已经数据发送完毕且关闭了. 我用过s ...
随机推荐
- Spring 中事务控制的API介绍
1.PlatformTransactionManager Spring所有事务代理类都是基于PlatformTransactionManager接口的实现. 此接口是spring的事务管理器,它里面提 ...
- 汇编语言--微机CPU的指令系统(五)(算术运算指令)
(3)算术运算指令 算术运算指令是反映CPU计算能力的一组指令,也是编程时经常使用的一组指令.它包括:加.减.乘.除及其相关的辅助指令. 该组指令的操作数可以是8位.16位和32位(80386+).当 ...
- centos6 自带python2.6升级python2.7+
centos6系统自带Python为2.6.6版本,升级搞版本操作如下(python2-python3都一样) 1.下载需要升级的python包 官方下载地址:https://www.python.o ...
- BDD实战篇 - .NET Core里跑Specflow - 可以跑集成测试和单元测试
这是<如何用ABP框架快速完成项目 >系列中和DevOps系列文章其中一篇文章. BDD很赞!比TDD先进很多,能够大大提高编码效率. 上一篇文章说了如何在.NET Core里安装 ...
- IDEA 代码格式化,快捷键
一键格式化代碼: Ctrl+Alt+L 全局搜索替换:ctrl+shift+r 强大的搜索功能,shift+shift (无论您想要搜啥都能找到) ctrl+shift+R==搜索类 CTRL+N ...
- git上传中的排除的配置文件, git实际的操作代码;
git上传中的排除的配置文件: git实际的操作 在主目录建立.gitignore文件并输入以下保存: *.class #package file *.war *.ear #kdiff3 ignore ...
- 关于js脚本宿主对脚本代码的绑定
脚本代码绑定,Unity3D是这样做的.为了体现Unity3D的基于对象设计,Unity3D可以为每个对象绑定多个脚本文件,可以是js,可以是cs,也可以是boo. threejs/editor也有与 ...
- python之模块使用
1.入口 """ 模块测试入口 """ import show_message as sm # 导入方式一 sm.show(sm.__nam ...
- Response()的对象
addCookie(Cookie cookie):这个方法是向Response容器中添加一个Cookie,然后服务器容器会自动的将这个Cookie回写给客户机的,至于Cookie的相关知识我们会在后面 ...
- List泛型与DataTable相互转换
public static class ExtensionMethods{/// <summary>/// 将List转换成DataTable/// </summary>/// ...