当前位置: 技术问答>linux和unix
【急问】:关于send()和recv()的问题
来源: 互联网 发布时间:2016-06-05
本文导语: 问题场景:发送端连续发送send()几百K的大包,接收端连续接收recv(),并把接收到的数据流存入接收buffer中; 问题:1。接收端会不会要多次调用recv()才能把一个包接收完? 2。如果上面的但是是“肯...
问题场景:发送端连续发送send()几百K的大包,接收端连续接收recv(),并把接收到的数据流存入接收buffer中;
问题:1。接收端会不会要多次调用recv()才能把一个包接收完?
2。如果上面的但是是“肯定”的,那么会不会出现这样的情况:在一次recv()得到是数据是前一个包的后面部分和后一个包的前面部分的组合?
3。如果第二个问题的答案也是“肯定”的,那么新的问题又出来了,当一个包还没recv()完整,现在就清空了接收数据的buffer,又重新recv()接下来的数据,并存入接收buffer中,那么现在怎么才能把数据中的完整包分离出来呢?
有什么好的解决方法呢?
问题:1。接收端会不会要多次调用recv()才能把一个包接收完?
2。如果上面的但是是“肯定”的,那么会不会出现这样的情况:在一次recv()得到是数据是前一个包的后面部分和后一个包的前面部分的组合?
3。如果第二个问题的答案也是“肯定”的,那么新的问题又出来了,当一个包还没recv()完整,现在就清空了接收数据的buffer,又重新recv()接下来的数据,并存入接收buffer中,那么现在怎么才能把数据中的完整包分离出来呢?
有什么好的解决方法呢?
|
这个问题是这样的(我以TCP为例来解释):
1、你说的发送端有几百K的大包,这里说的不严密吧?应该是有几百K的数据吧。因为在IPv4的网络里,一个IP包
最大是65535,不可能达到你说的那种一个包几百K。所以我假设你说的是几百K的数据。
2、如果是几百K的数据,那么首先是从应用进程缓冲区将数据写到内核缓冲区,通常是执行write(),write()返回
了以后,也只是说你成功的将数据由引用进程拷贝到了内核缓冲区里面去了,至于能不能安全的到达对端,还是未
知数。
3、这样的数据被发送到对端,首先到对端的内核缓冲区,然后从内核缓冲区再拷贝到应用程序的缓冲区。也就是
rcv()的过程,因为数据可能被分成很多个包,所以可能需要多次调用read()才行。在收端读完数据以后,会给发
送端回确认消息,这时候发送端才会删除内核缓冲区中的数据,否则过一段时间没有收到确认消息,会重发的。
4、因为TCP是面向字节流的协议,所以很可能上层数据被分割到多个TCP包里面去了。但是在接收端这面,又会重
新的组合在一起的,再加上TCP的超时重传和确认分组机制,可以保证数据不会丢失,不会乱序。
5、如果是包过大,超过了MTU,会有IP包的拆包和重组,这个不用担心,是内和协议栈的IP部分自动处理的。
|