精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
通信连包是指接收时收到了发送端多次混合起来的多组小数据包,这时候多组只按一组处理,就会丢失数据,这是最致命的问题。在通信时,理想状态是一发一收,发送端和接收端都好处理,但是实际上理想状态总是有偏差的。通信阻塞时,阻塞在接收或发送电脑上,阻塞在网络节点时,就会产生连包。这就像水闸放船,本来一次放一个,结果阻塞时一次放了几个,如果水闸管理处不能及时处理,就会出问题,一直阻塞。回到电脑环境里,这一直阻塞最终有可能导致操作系统通信栈压力大崩溃。在大并发操作系统通信负荷大、模拟环境虚拟机性能差、进程线程多进程通信负荷大和网络节点通信压力大,偏差波动越来越大,就会产生连包。
SOCKET、套接字连包和TCP连包经常放到一起来讲,因为TCP的缓冲机制,容易让小包聚集在接收端,这时候可以启用SOCKET的TCP_NODELAY,不让TCP算法缓冲数据,把延迟去掉,就容易解决连包。不过TCP_NODELAY只有在问题确实解决不了,明显觉得网络反应慢时才启用,正常情况下启用有可能降低TCP的整体效率。在实际处理通信协议时,最好是长度和包标志都带上,类似TCP底层的包结构。
我经常开发通信软件,一般不开TCP_NODELAY。
把长度和包标志都带上后,通信软件的架构要设计合理,比如典型的IOCP模式下,用几个线程来处理通信包,如果线程内效率差就不好解决连包问题。一般select加多线程的通信架构下,合理调节线程的个数,加强通信效率,会避免连包。另外和用户交互的模块,收原始数据的模块,和通信模块之间的互动,也要处理好,如果用队列和缓冲,生产者和消费者要及时处理。
C++一般用原生函数send和recv处理,不太好实现流式缓冲处理,不过网上有源代码封装的不错,大家可以找找。C#的NetworkStream和MemoryStream类似类比较多,处理方便。如果初学者不太好用C++掌握,用C#开发相应的处理代码,容易掌握流的原理。锐英源软件用C#开发过教育平台,平台里有组播和点对点通信,通信状态很复杂,但是用好了C#流处理,处理好了SOCKET连包和TCP连包问题。
如果大家想证实连包情况,可以用wireshark抓包,如果操作系统卡,觉得wireshark不方便打开,用tshark来抓包也行,在卡的时候,迟迟收不到发送端的数据包,在突然收到时就会是连包情况。
连包在小包时经常会出现,大家要注意。