为什么将此方法特别弄一个专集,因为在通信软件领域中,数据接收一直是一个比较有复杂的事情,处理的好不好,直接影响到程序效率。
本文就是为了介绍NetHost::Recv配合mdk这套引擎,如何方便的解决了传统通信软件中在数据接收这一块上遇到的各种瓶颈
瓶颈1:等待数据的方式
循环sleep、阻塞recv、事件触发(例如select epoll)
他们的缺点
循环sleepcpu吃紧
阻塞recv占用业务线程
事件触发,不知道有多少可读数据,如果数据不完整,读出数据需要用户自己维护
NetHost的解决方案
NetHost有自己的接收缓冲,mdk引擎收到数据首先放入NetHost的接收缓冲,然后触发OnMsg。
因为底层已经在接收了,所以recv永不阻塞,数据不够直接返回,等下次数据到达时,OnMsg会再次被触发
瓶颈2:一个完整消息被分成多次到达
来1次收1次,记录上次接收状态,用户自己拼包
缺点
用户得自己维护已接收的数据,相当于一个接收缓冲,这个缓冲必须随着连接的建立与断开创建与删除,维护代价昂贵
NetHost的解决方案
NetHost::Recv比传统的recv方法增加一个bClearCache参数,告诉Recv接收到数据后,是否将数据从接收缓冲删除
bClearCache为true时,与传统recv方法效果一样,比如到达数据123456789
recv 2 byte 收到12
recv 2 byte 收不到12了,收到34
bClearCache为false时,读出数据不被删除,下次还可以读到,比如还是到达数据123456789
recv 2 byte 收到12
recv 2 byte 还是会收到12
应用举例
比如比如报文格式:2byte内容长度+报文内容
到达数据0x00 0xff 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39
实际就是257byte的报文,报文内容255byte,实际达到“123456789”9byte
按照传统做法
1.Recv(msg, 2);0x00 0xff被读出
2.解析msg得到内容长度,假设为255
3.Recv(msg, 255);返回长度不够,123456789被读出
这时,直接return吧,数据就丢失了,用户得建立缓冲
NetHost::Recv的做法
1.Recv(msg, 2, false);0x00 0xff被读出,但是不从缓冲删除
2.解析msg得到内容长度,假设为255
3.Recv(msg, 257);报文长度2+255,返回长度不够,1个byte都不读取,0x00 0xff "123456789"依旧在缓冲中
用户可以直接return,等待下次OnMsg触发时再尝试读取
等到数据全部到达时第3.步骤就直接全部读出来,并从缓冲删除了,1次解决
用户不需要sleep,不需要阻塞,不需要维护缓冲
就是这样,有什么问题欢迎联系我
本文就是为了介绍NetHost::Recv配合mdk这套引擎,如何方便的解决了传统通信软件中在数据接收这一块上遇到的各种瓶颈
瓶颈1:等待数据的方式
循环sleep、阻塞recv、事件触发(例如select epoll)
他们的缺点
循环sleepcpu吃紧
阻塞recv占用业务线程
事件触发,不知道有多少可读数据,如果数据不完整,读出数据需要用户自己维护
NetHost的解决方案
NetHost有自己的接收缓冲,mdk引擎收到数据首先放入NetHost的接收缓冲,然后触发OnMsg。
因为底层已经在接收了,所以recv永不阻塞,数据不够直接返回,等下次数据到达时,OnMsg会再次被触发
瓶颈2:一个完整消息被分成多次到达
来1次收1次,记录上次接收状态,用户自己拼包
缺点
用户得自己维护已接收的数据,相当于一个接收缓冲,这个缓冲必须随着连接的建立与断开创建与删除,维护代价昂贵
NetHost的解决方案
NetHost::Recv比传统的recv方法增加一个bClearCache参数,告诉Recv接收到数据后,是否将数据从接收缓冲删除
bClearCache为true时,与传统recv方法效果一样,比如到达数据123456789
recv 2 byte 收到12
recv 2 byte 收不到12了,收到34
bClearCache为false时,读出数据不被删除,下次还可以读到,比如还是到达数据123456789
recv 2 byte 收到12
recv 2 byte 还是会收到12
应用举例
比如比如报文格式:2byte内容长度+报文内容
到达数据0x00 0xff 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39
实际就是257byte的报文,报文内容255byte,实际达到“123456789”9byte
按照传统做法
1.Recv(msg, 2);0x00 0xff被读出
2.解析msg得到内容长度,假设为255
3.Recv(msg, 255);返回长度不够,123456789被读出
这时,直接return吧,数据就丢失了,用户得建立缓冲
NetHost::Recv的做法
1.Recv(msg, 2, false);0x00 0xff被读出,但是不从缓冲删除
2.解析msg得到内容长度,假设为255
3.Recv(msg, 257);报文长度2+255,返回长度不够,1个byte都不读取,0x00 0xff "123456789"依旧在缓冲中
用户可以直接return,等待下次OnMsg触发时再尝试读取
等到数据全部到达时第3.步骤就直接全部读出来,并从缓冲删除了,1次解决
用户不需要sleep,不需要阻塞,不需要维护缓冲
就是这样,有什么问题欢迎联系我
来源:oschina
链接:https://my.oschina.net/u/732357/blog/86732