最近在处理框架通讯方面的问题,通过积累的开发经验,其实在很多情况(尤其是实时大数据量),udp是占有很多优势的;不需要连接,只管发送,理论上要快很多;

另外在穿墙上占有很大优势;

但是最大的一个问题就是丢包;

很多时候我们会结合我们的业务来进行发送与回执,这样的方式应该是最好的;但是也意味着每次都得重来一次;因此花费了一些时间来写这个重发逻辑;当然目前仅是测试;

封装了一个udp重发;其实组播也可以直接使用,只是我还没有完成封装,原理一样,只不过组播封装重发,会浪费网络资源,只要一个节点(把一个接收位置看作一个节点)没有收到其中一个包,就需要发送端发送,所有节点都会接收(并不影响数据完整,在接收端已经封装了接收方式,不会造成数据重复);不说组播了,回到udp重发;

大体结构:

1.每一次发送都视为session;

1》judpclient为封装的发送端,发送数据时,会自动分包,按照udp65535大小(可以设置);每次发送分配一个发送端session(同时产生id),每次发送分包时,都会依次产生

一个初始化序列号,按照初始序列号,每包设置一个id,按照此发送打包数据发送

2》同时会发送一个ack发送确认包,防止数据包只有一个被丢包;

3》发送后等待数据返回

4》judpclient关闭只是逻辑关闭

2.接收端

接收端按照来源IP,端口产生一个接收端session,然后接收数据,组织数据,检查丢包,发送丢包ack;

接收端设计了serversession及buffer,所以不用担心数据重发造成数据重复的问题,该结构读取方式已经直接避免了

3.辅助应用

因为是辅助,无法判断judpclient使用情况,所以利用java特点,在回收对象时设置逻辑关闭;同时控制时间,来判断通讯真实关闭(因为发送端还要监听等待重发)

4.共享session

最开始的设计是不共享的,但是在测试时发现,在极端时候,因为发送端占有端口监听需要时间,重新初始化judpclient对象,会导致端口占用完,无法再分配;所以

最后采用了共享的方式,让多个judpclient实际使用一个真正的udp底层通讯;每个judpclient产生一个id,来判断数据接收时往哪里发送,触发哪个对象的方法;

5.缓存问题解决方式

数据重发就意味着发送的数据需要缓存下来,准备重新发送;这样如果发送大量数据,发送端就可能“爆满”,所以要减少内存使用;

处理方式:做一个简单的数据量统计(不精确,也不需要精确),当这个量达到一定值后,就把数据由内存转移到磁盘中;

我自己设计了一个文件保存方式(做了一个文件持久化层),来按照一定方式保存,也实现了文件删除,修改(修改没有必要);

里面主要是有个索引维护;同时使用了内存数据库表(如果不实现文件修改是没有必要的,通过异步方式保证文件索引准确,又不影响使用效率)

最开始我没有使用文件,而是查找了数据库(paldb,fastdb,mapdb等等),但是效果不尽人意,通过磁盘,其实一般磁盘读取在30M/s,而数据库是做不到的;因此我直接采用了文件读取方式;我并不是要做一个文件数据库,所以在实现文件修改时,任然使用了第三方数据库h2,简单直接,索引使用足够了,而且是异步;在数据重发这里,文件修正是没有必要的,实现该功能只是想让模块更加完整而已;

文件保存,也是通过一个简单的计数,每次10M左右的数据一起写入文件;

当接收端数据接收完成后,会回复一个接收完成ack包,发送端解析信息后,会把接收完成的一次会话数据都删除掉;

使用数据库保存的最初代码我并没有删除,只是没有使用而已;

6.遗留问题(需要优化)

通过什么的构造,其实最大问题在于我无法控制judpclient的使用,这样会造成很多线程启动,在监听数据返回的信息(丢包,完成),这样造成大量线程存在,虽然应用了线程池

根据现在的测试,发送端cpu 15-35%都是有可能的;阻塞的线程也很多,一旦彻底完成发送,同时退出的线程同样多,但是感觉这样也没有影响测试使用(可能是我的java水平不过关,有的测试结果我感觉很怪);所以需要缩减线程以及阻塞集合;

7.共享session分配

专门有个管理池分配,其实就是定一个最大个数,使用完了就再产生一个,同时监视是否共享session关闭情况

8.其它辅助实现

使用了guava的缓存及eventbus;

数据发送打包与解析配套(接收端也可以正常使用)

9.源码

eclipse编译;现在已经上传git;

地址:https://github.com/jinyuttt/jyudp.git

我也会上传到csdn,不过可能超过大小;

10.基本可以测试使用了,优化后性能好了很多

udp重发的更多相关文章

  1. udp重发java实现

    最近在处理框架通讯方面的问题,通过积累的开发经验,其实在很多情况(尤其是实时大数据量),udp是占有很多优势的:不需要连接,只管发送,理论上要快很多; 另外在穿墙上占有很大优势: 但是最大的一个问题就 ...

  2. udt通信java

    udt协议是什么? 简单的是udp重发 经过上次的修正,重新测试,修复,测试各种环境,再次查找出源码错误,重新修正 修正内容在git中的修正说明中 同时针对之后的应用,对封装的代码也做了修改和重构 代 ...

  3. .net学习笔记---tcp/udp/http/socket

    什么是TCP和UDP,以及二者区别是什么? TCP的全称为传输控制协议.这种协议可以提供面向连接的.可靠的.点到点的通信. UDP全称为用户数据报协议,它可以提供非连接的不可靠的点到多点的通信. 使用 ...

  4. TCP 三次握手四次挥手, ack 报文的大小.tcp和udp的不同之处、tcp如何保证可靠的、tcp滑动窗口解释

    一.TCP三次握手和四次挥手,ACK报文的大小 首先连接需要三次握手,释放连接需要四次挥手 然后看一下连接的具体请求: [注意]中断连接端可以是Client端,也可以是Server端. [注意] 在T ...

  5. OSI参考模型及各层功能,TCP与UDP的区别

    OSI参考模型:ISO/IEC 7498标准定义了网络互联的7层结构模型,即开放系统互连参考模型. OSI参考模型定义了开放系统的层次结构.层次之间的相互关系,以及各层所包括的可能的服务.OSI的服务 ...

  6. UDP协议开发

    UDP是用户数据报协议(User Datagram Protocol,UDP)的简称,其主要作用是将网络数据流量压缩成数据报形式,提供面向事务的简单信息传送服务.与TCP协议不同,UDP协议直接利用I ...

  7. RUDP之一 —— UDP VS TCP

    原文链接 原文:http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/ 介绍 大家好,我是Glenn Fiedler, ...

  8. 成功进行了一次UDP打洞

    本次测试参数:服务端是公网固定IP:两个客户端A和B分别位于不同电脑,不同宽带,不同型号路由后面(一个家庭路由,一个企业路由),且路由没有经过特别的设置.测试没有什么特别的地方,只是依照网络资料进行实 ...

  9. HTTP,FTP,TCP,UDP及SOCKET

    一.TCP/IP协议简析TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层:网络层:IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议传输层:TCP协议与UDP协议应用层:F ...

随机推荐

  1. vue 配合vue-resource调用接口,获取数据

    1.先用node+express+mysql简单配置一下后台 const express = require('express');const mysql = require('mysql');con ...

  2. 1040 mysql Too many connections

    笔者在项目中遇到mysql 出现:1040 too many connections 异常,意思是超过数据库最大连接数,打不开表结构信息.笔者排除问题建议:1.查看程序代码是否存在BUG:2.检查代码 ...

  3. informix 随笔

    1.新建连接create new database connection 2.database Url:  jdbc:informix-sqli://119.84.39.35:29999/gps_pr ...

  4. PYTHON之路,线程

    关于多任务的理解, 代码要执行,首先得变成机器认识的东西执行,那么需要解释器.那么执行按道理,一段程序在这里就具体来说一段代码的执行吧,我们知道代码的执行是从上至下按顺序执行,那么这里有条件分支结构, ...

  5. Ubuntu系统安装Transmission

    虚拟机Ubuntu 16.10 Transmission 2.92(https://launchpad.net/~transmissionbt/+archive/ubuntu/ppa) 一.添加源 s ...

  6. C#利用首尾時間計算中間時間差

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  7. BF匹配器

    对于BF匹配器,首先我们得用cv2.BFMatcher()创建BF匹配器对象.它取两个可选参数,第一个是normType.它指定要使用的距离量度.默认是cv2.NORM_L2.对于SIFT,SURF很 ...

  8. Java中反射的实现方式

    所谓反射,是指在运行时状态中,获取类中的属性和方法,以及调用其中的方法的一种机制.这种机制的作用在于获取运行时才知道的类(Class)及其中的属性(Field).方法(Method)以及调用其中的方法 ...

  9. virtualenvwrappers pipreqs 踩坑

    virtualenvwrappers 1.安装 pip install virtualenvwrapper 在~/.bashrc 中写入 export WORKON_HOME=~/.virtualen ...

  10. 【DevExpress】GridView的RowClick事件禁用Checkbox选择的解决办法

    添加GridView的RowCellClick事件,代码如下 private void gvBoxMails_RowCellClick(object sender, DevExpress.XtraGr ...