Tcp消息沾包与心跳包发送问题

  TCP和UDP想必是通讯中用的最多的协议了,具体的协议规则就不介绍了,在此只是记录一下在项目中遇到的一些问题,文字没有怎么组织,基本上是想到哪写到哪,莫怪.......
  tcp问题一:心跳包
  因为tcp的长连接问题,需要保活连接,常规的做法就是发送心跳包,通过往服务器一端发送一小段数据包,接收端可以不处理。考虑到这种需求,mSocket.sendUrgentData(0xff);这个方法可能会很合适,因为接受端接受到这种消息会自动忽略,不需要自己着手处理。在测试中,发现通过该方法由手机端发送心跳到pc上,pc为xp系统tcp连接正常,不会断线,而在win7系统时,tcp连接会在80s准时断开,虽然有重连机制,但是频繁的重连还是会影响性能。经过一段时间的排查,发现原因是在win7上,发送sendUrgentData该数据最多只能发送16次,而我的心跳包是5s发送一次,正好是80s。在win7上发送sendUrgentData数据16次会造成网络拥塞,造成连接中断。
  tcp问题二:消息沾包
  在移动端接收pc发送的tcp消息时发现会有两个甚至多个数据沾包的情况,造成两个消息粘连在一起,接收端解析消息时发生错误,并且这种情况只是在网路状况较差时发生。在TCP中因为三次握手原理,发生数据会接收ack的反馈,如果频繁的发生的小数据消息,会造成网络的拥塞,影响性能,因此为了防止网络中频繁的有小数据发生,tcp底层会启用nagle算法,每个tcp套接字都有一个缓冲区,每次发送其实都是从这个缓冲区中取数据发送,只有当数据包的大小达到套接字的缓冲区大小才会发送,在项目中由于我发送的是很小的字符串消息,它会等待下一个消息到达一定大小一起发送,这个tcp套接字缓冲区大小由系统内核缓冲区大小决定,这也就造成了消息沾连在一起的情况。解决的办法有以下几种:一,连续发送多个消息时,每个消息间隔40ms发送,tcp发送消息会有两个前提,一个是数据大小达到缓冲区大小马上发送,再者就是数据没有达到缓冲区大小,但是40ms还没有数据进入缓冲区,此时也会发送(有些说法是200ms,但经过测试在linux系统只有40ms,Android内核属于linux,因此只需在发送消息时间隔40ms);二,设置tcp无延迟,也就是不启用nagle算法,如果不设置是会默认开启,不启用的方法也很简单,调用mSocket.setTcpNoDelay(true);即可。但其实这种解决办法在需要高效率的网络通讯其实是不适用的,因为你可能无法忍受每次发送消息都得有40ms的延迟,而不启用nagle算法,频繁的发送小数据,又会造成网络拥塞,同样是会严重影响通讯性能的,所以在网络编程时最好避免这种多次发送,在接收的模式,应该保持“一发一收”的模式。
 
 

你可能感兴趣的:(tcp,sendUrgentData,nagle,心跳包,消息沾包)