热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

数据传输稳定性优化

1.消息粘包:实际:M1和M2同时到达,并且被同时接收,最后才接收M3.此时M1和M2就出现了消息粘包2.消息不完整:解决:如何解决有序的混传数据:三种方案:提倡使用第二种:固定头

项目地址:https://download.csdn.net/download/weixin_42528855/12549389

 
1.消息粘包:


实际:M1 和  M2 同时到达,并且被同时接收 ,最后才接收M3.

此时 M1 和  M2 就出现了消息粘包

2.消息不完整:

解决:

如何解决有序的混传数据:

三种方案:

提倡使用第二种:固定头部

 起止符方案:需要一个一个字节的依次检测(很耗费时间)

 头部的4个字节保证了后面的100个字节可以一次性传输,无需检查(可以避免消息粘包和丢失)

代码还是基于NIO的多人聊天室进行改动,但是对于多线程的部分没有进行改动:

1. 首先提供了一个  :公共的数据封装 类:

 
为什么会使用packet?

这里的主要目的是构建3层缓存,对于发送的数据是多样性的,我们需要一个统一的封装,Packet就是不错的选择。

当我们在发布数据之前会先封装为统一的Packet,Packet可以提供基础的Stream操作,随后会到达第二层,也就是Frame层,将一个包转化为不同的帧。对于包和帧都是有意义的,有实际的反向解析操作。

当我们到达真实需要发送的位置会将帧转化为IoArgs,此时就没有上层业务意义了,更多的是数据的载体。

这样的方式可以做到3层缓冲,同时也可针对不同层面做不同的调度,这也增加整体的框架调度性能。

 
接收消息:

2. 分析一下 AsyncReceiveDispatcher 类(处理 StringReceivePacket的类【ReceivePacket的子类】 )

在 AsyncReceiveDispatcher 类 中 关注 两个函数:

start() 和 registerReceive()

在 registerReceive()  中启动了 接收者的 receiveAsync(ioArgs); 异步接收类,

注意:start() 是在   Connector 类中的 setup函数里 启动的:

// 启动接收
receiveDispatcher.start();

receive涉及了三个回调: 这是慕课网上一位 昵称为:慕勒1089785  的大佬总结的

这三个回调基本就完成了数据接受的一个过程

第一个就是 上级SocketChannelAdapter实现了HandlerproviderCallback的接口,并且将其注册到了IoSelectorProvider之中,当可以处理数据时,下层就回调了接口中的方法。上级就让其来真正的实现接受。如用IoArgs来读取数据之类的。

第二就是,上层ReceiverDispatcher实现了IoArgsEventListener接口,并在SocketChannelProv中注册了,当下层IoArgs读取到数据之后,就会回调给上层,ReceiverDispatcher就会处理这个IoArgs,打包成Packet。

第三就是,Connector实现了一个回调接口,并在ReceiverDispatcher注册了,当下层Packet打包完成之后,就会回调给上层,让Connector打印数据。(Server还需要广播)。


发送消息:

发送消息相对于 接收消息 要简单一些,但是也涉及到了回调函数:

第一个就是 上级SocketChannelAdapter实现了HandleOutputCallback的接口,并且将其注册到了IoSelectorProvider之中,当可以处理数据时,下层就回调了接口中的方法。上级就让其来真正的实现接受。将写线程交给线程池来处理。

第二就是,上层AsyncSendDispatcher实现了IoArgsEventListener接口,并在SocketChannelProv中注册了,当下层IoArgs读取完Packet数据之后,就会回调给上层,ReceiverDispatcher就会处理这个IoArgs,如果没有发完,则继续发送当前包。

 
总结:


发送和接收的流程:




推荐阅读
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
author-avatar
__wolf狼
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有