关于QNX下TCP/IP通信的实时性的一个问题,请教XTANG及各位高手!

我现在做的项目遇到一个问题(QNX4.25),大概是这样,我这边作为CLIENT在跟对方SERVER建立STREAM连接后每300MS向SERVER发一个11字节的数据包,但结果是SERVER只能偶尔正常接受数据,多数情况下SERVER总是在1S甚至2S后才收到我的数据包的情况,而且此时一收就是3个或者5个包(以下简称累积包)连续收到这样的情况。因为SERVER要求必须在1S内有数据收到,不然就认为连接中断,就会关闭这个连接而等待重连,所以我的连接总是被挂断。

我这边作为CLIENT尝试用两种方式发送数据:
一是用300MS的定时器发送,结果如上所述,SERVER收到累积包的时间间隔大概是3-5秒。就是说每次正常通信3-5秒后,SERVER因为在1S内未收到CLIENT发送的数据就会挂断连接以至通信中断。
二是用查询方式,即我的发送进程不断去查询当前的系统时间,如果时间已经过了300MS,就发送一包数据,用这样的方式,发现通信效果就好很多,SERVER收到累积包的时间间隔大大加长,最短3分钟,最长10分钟。就是说每次能正常通信3-10分钟了。但SERVER依然会收到累积包,我的连接依然会被挂断。

因为我发送的是11个字节的小数据包,所以我尝试打开TCP_NODELAY选项,结果是对上面第一种发送数据的方式有明显效果,正常通信的时间可以加长到20分钟。对第二种方式几乎没什么效果。但尽管如此,也不能从根本上解决通信中断的问题。

就这个现象,我想请教一下XTANG先生,也希望与各位高手探讨一下。
1、为什么上面提到的两种发送方式会有不同的效果。
2、CLIENT发送的数据包是在哪里被延迟了呢?我想应该不是在我的发送进程里,那应该是在操作系统一级上被延迟了吗?为什么会延迟,怎么解决这个延迟呢?
3、或者延迟是发生在了SERVER端吗?SERVER端使用的是DOS系统,因为DOS不是多进程的,所以I/O采用非阻塞的方式。
4、希望大家给我出出主意,让我怎么样能解决这个问题。

另外需要说明的就是,在CLIENT和SERVER双方建立连接后,SERVER也每300MS向CLIENT发送几十或者不超过三百个字节的数据。CLIENT这边总是能正常受到SERVER发来的数据,从未发生累积包的现象。

谢谢!

STREAM(TCP)的定义就是可以把你交给protocol的数据,任意组合以后发送的。它从来不保证你的每一个 write()/send()/sendto() 会变成一个数据包发送出去。

你的情形,通常应该使用 UDP,以保证每一个数据包的正确发送。对于UDP的非可靠性,通常通过接收端发回ACK来确认。

谢谢XTANG先生。我是想就这个问题跟您及各位同仁探讨一下。

1、为什么我采用两种发送方式会有不同的效果呢?
2、下面是一段关于TCP_NODELAY的解释,我现在不知道它的出处。
The TCP_NODELAY option disables the Nagle algorithm. The Nagle algorithm is used to reduce the number of small packets sent by a host by buffering unacknowledged send data until a full-size packet can be sent. However, for some applications this algorithm can impede performance, and TCP_NODELAY can be used to turn it off. Application writers should not set TCP_NODELAY unless the impact of doing so is well-understood and desired, since setting TCP_NODELAY can have a significant negative impact on network performance. TCP_NODELAY is the only supported socket option which uses level IPPROTO_TCP; all other options use level SOL_SOCKET.
我对它的理解就是打开这个选项能够阻止累积包的产生,从而增加通信的实时性。同时再QNX的HELP里也有类似的说明。
3、我希望能通过这样探讨得到一些启发,从而解决我的问题。

最后说明一下,之所以不用UDP,是因为这个项目是跟另外一个系统接口,而这个系统是运行在DOS上的,而且只提供了TCP的通信接口。

这个问题跟TCP和UDP的特性有关。TCP_NODELAY的说明是对的,但打开它只能“减少”累积包的产生,并不能“保证”消除累积包的现象。

TCP的特性是保证可靠性,但它牺牲了“数据包”的概念。数据在TCP上是作为“流”来传送的(这也是SOCK_STREAM的出处)。因为TCP为了保证靠性,又有效使用网络资源,TCP里有大量的算法来延迟,累积用户提交的数据。TCP的使用者,是无法预测和回避这种延迟和累积的。