本题不讲基础,讲的是实际应用。首先项目内采起Socket,想必都是从 长链接 频繁数据通信出发,但大多数人使用的时候都是采用了堵塞方式去建立Socket,堵塞方式:每产生一个链接,服务端就要开启一个线程来处理,没处理完成不能退出,客户端会一直在等待结果返回, 非堵塞方式:基于反应器模式,多路并发,多路复用,事件来了就处理,处理完成就归还,相信对线程熟悉的老哥们这时候确定会想到了用线程池管理,没错,这就是非堵塞的优点之处。缓存
当前有100个客户端链接服务端,堵塞方式:就要打开100个线程来处理,不能重复回收复用,由于你要服务完你接待的上帝(客户端)才能够结束 非堵塞方式:只须要开30个线程,经过线程池管理,处理完成事件回收、复用 咳咳咳,看到这里你们应该明白这两种模式的好坏取舍了,固然,这对于客户端来讲是看不到的,主体说的是服务端的性能了,有点跑题了!!并发
咱们用Socket就是长连接频繁数据通信,居然有通信,那么就离不开数据交互。不知道各位大大有没有接收过超过1024字节的数据呢?如一张动态图片、文件之类。 若是有,那么应该能猜想到小二我准备说的主题了,没有接收过的同窗,请注意认真听讲了喂!!!框架
场景:服务端向客户端发送一张8M动态图片,客户端轮询读取接收,接收到通知UI出列刷新,听起来流程一点问题没有是否是? no!no!no! 同窗,要是这样简单我就对不起铺垫了,服务端确实是整个图片发出去了,可是因为字节多大,通信框架处于好心,主动帮咱们把8M 的数据字节流拆成了N多个包发送给客户端,so 前面客户端接收到的只是某一个包,而不是完整的8M动态图性能
聪明的童鞋可能想到了,那咱们本身来分包处理,这样就不会处于被动了.这里又引起一个问题。 怎么分包?分几个包?客户端怎么知道那几个包组合起来是一个完整的包? 分包:咱们先把数据转成字节流,在转成进制字符串,在进行字符串拆分便可线程
分几个包:一般客户端在读取的时候都会设置一个长度(readLine获取)因此这里咱们也不用过于纠结,服务端1024字节或者其余来拆分均可以。3d
假设服务端把8m动态图分红了8个数据包下发?客户端接收后怎么判断是否完整包?cdn
来,各位看官发挥一下想象力-_-blog
想想咱们转成了进制字符串,那咱们可不能够在上面作一下手脚处理呢? 答案固然是 能够的啦!!队列
咱们能够在没拆分前的进制字符串头和尾添加标识字符,例如:进制字符串是 88777222777 ,咱们用AA来看成标识字符:AA88777222777AA。 这样看起来客户端是否是很明确的知道怎么去处理了呢?事件
客户端只要接受收据,碰到AA做为开头的数据包,就缓存起来放进队列或者本身的缓冲变量,等到碰见AA结尾的数据包,就总体拼接,剔除开头结尾的AA,这样不就是一个完整的数据包了么? ps:这里还有一个小问题, 有时候通信频繁的时候一些不可知因素还容易产生数据缺失,因此咱们上面的方法还有一点缺陷,咱们不知道字节数对不对。 想一想看,咱们都能在没拆分前的进制字符加上AA标识,为何不能把长度也加上去呢?
如上图所示,咱们能够和客户端约定好数据协议,这里有没有写过串口的童鞋呢?那么接触起来没有丝毫困难! 起始位+数据包长度+数据+结束位,这里的数据处理都是用进制字符哦,咱们能够这样设置 起始位 2个字节+数据包长度 1个字节+数据 n个字节+结束位 2个字节,不熟悉字节和进制的童鞋,你要好好补一补基础了。 如上流程,那么客户端在拿到一个开头结尾都是AA的完整数据包以后,在取出第三个字节的数据包长度,判断一下数据包就可知道是否完整了 最后~ 状况固然不会那么少了,还有
等等呢,小二今天还有事情,下次有时间在和各位大大具体分析了,by~