关于ns3中socket往tcp传递产生丢包问题

来源:互联网 发布:淘宝c店最低折扣设置 编辑:程序博客网 时间:2024/06/08 09:23

问题描述

        近日调试我那 pub/sub 系统仿真的时候,发现当 pub 发送的包速率快到一定程度之后,莫名其妙的收端就会丢包。调试了一整天,看各种 trace 和 log 终于发现问题出在发端 socket。


庖丁解牛

       我们知道 TCP 协议是保障消息可靠性的,在 ns3 中基本上可以认为丢到 TCP 层的包是不会丢失的。
       所以显而易见,问题要不就是出在收端应用层没有处理 TCP 递交的包,要不就是根本没有发出去。
       二选一么,当然不能扔硬币。我们去看trace文件好了。ns3 提供的 AsciiTrace 可以详细记录每个网络层包的发送情况。使用方法大致长这样:
 AsciiTraceHelper ascii;  Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream ("文件名");

       运行,然后去看生成的文件,找到这么一行
t 0.140524 /NodeList/0/$ns3::Ipv4L3Protocol/Tx(1) ns3::Ipv4Header (tos 0x0 DSCP Default ECN Not-ECT ttl 64 id 221 protocol 6 offset (bytes) 0 flags [none] length: 576 192.168.0.1 > 192.168.2.1) ns3::TcpHeader (49154 > 8080 [ ACK ] Seq=49313 Ack=1 Win=65535) Payload Fragment [2152:2283] ns3::AppHeader (the 76 message in topic test has the content abc) Payload (size=71) ns3::AppHeader (the 78 message in topic test has the content abc) Payload Fragment [0:210]

     
 稍微解读一下 ns3 的 AsciiTrace 。为首一个 t 代表这是一条发送消息。后面0.140524是时间,单位是秒。再后面 /NodeList/0/$ns3::Ipv4L3Protocol/Tx(1) 是节点信息,也就是这条记录是哪的。紧接着后面就是包头信息,都以 XXXHeader 开头:首先是 IP 头,不管他;后面是 TCP 头,也不管他;再后面是 AppHeader ,名字是我自己起的,我们看他后面的()中打印出来的信息,就看消息编号,神奇了,第77条哪去了?
       所以结论就很明显了:pub 端就没有把消息发出去,但是消息确实是一条一条 send 的,结果到了TCP就没了,那问题只能是 pub 端和 TCP 之间。那里有什么?凶手出现了socket !

解决之道

       找到“元凶”那接下来得找“作案手法”。我们在 ns3 中发消息时会调用
Socket -> Send(Packet);

        该函数调用 TCP 的 send。 TCP 是有发送的,当窗口不够大时,TCP 会拆包。但是问题来了,ns3 里面 socket 不会拆包,所以socket 的 send 函数中先会判断下层的窗口是否够大,够大那就发包,要是不够大,那就返回-1,等待应用处理。
       所以当发送速率很快的时候,77号消息发现窗口不够大,所以返回了-1,结果我没处理,当78好消息发送时,发现窗口又足够大了,所以在 TCP 看来76号消息后面跟的就成了78号消息。
       这样看来处理就简单了,对症下药。

方法一

       处理返回值,如果是-1那就等会儿再发

方法二

       也是我选择的方法,在发送前调用 Socket 的 GetTxAvailable() 方法取得 TCP 窗口空闲大小,足够大再发包。
0 0
原创粉丝点击