Python中send()和sendall()的区别

估计每个学习Python网络编程的人,都会遇到过这样的问题:

  • send()sendall()到底有什么区别?
  • send()sendall()原理是怎么样的?
  • send()sendall()能做什么事情?
  • 到底是使用send()还是sendall()

看完下面的文章,应该就能明白了

知识补充

首先会对一些常见的网络编程知识进行补充下:

MTU

通信术语 最大传输单元(Maximum Transmission Unit,MTU)是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位)

以以太网传送IPv4报文为例。MTU表示的长度包含IP包头的长度,如果IP层以上的协议层发送的数据报文的长度超过了MTU,则在发送者的IP层将对数据报文进行分片,在接收者的IP层对接收到的分片进行重组。

TCP传输的可靠性

  • 应用数据被分割成TCP认为最适合发送的数据块(根据MTU设定)。这和UDP完全不同,应用程序产生的数据长度将保持不变。由TCP传递给IP的信息单位称为报文段或段(segment)。

  • TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。当TCP收到发自TCP连接另一端的数据,它将发送一个确认。TCP有延迟确认的功能,在此功能没有打开,则是立即确认。功能打开,则由定时器触发确认时间点。

  • TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段(希望发端超时并重发)。

  • 既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。

  • 既然IP数据报会发生重复,TCP的接收端必须丢弃重复的数据。

  • TCP还能提供流量控制。TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。

send()

使用send()进行发送的时候,Python将内容传递给系统底层的send接口,也就是说,Python并不知道这次调用是否会全部发送完成,比如MTU是1500,但是此次发送的内容是2000,那么除了包头等等其他信息占用,发送的量可能在1000左右,还有1000未发送完毕

但是,send()不会继续发送剩下的包,因为它只会发送一次,发送成功之后会返回此次发送的字节数,如上例,会返回数字1000给用户,然后就结束了

如果需要将剩下的1000发送完毕,需要用户自行获取返回结果,然后将内容剩下的部分继续调用send()进行发送

sendall()

sendall()是对send()的包装,完成了用户需要手动完成的部分,它会自动判断每次发送的内容量,然后从总内容中删除已发送的部分,将剩下的继续传给send()进行发送;

源码

send()是直接调用的系统底层接口,所以Python源码没有,只有C的,由于不是很懂C,所以就没有去找C源码了

下面的源码是从pypy中复制出来的


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

def send(self, data, flags=0):
"""Send a data string to the socket. For the optional flags
argument, see the Unix manual. Return the number of bytes
sent; this may be less than len(data) if the network is busy."""
with rffi.scoped_nonmovingbuffer(data) as dataptr:
return self.send_raw(dataptr, len(data), flags)
 
 
def sendall(self, data, flags=0, signal_checker=None):
"""Send a data string to the socket. For the optional flags
argument, see the Unix manual. This calls send() repeatedly
until all data is sent. If an error occurs, it's impossible
to tell how much data has been sent."""
with rffi.scoped_nonmovingbuffer(data) as dataptr:
remaining = len(data)
p = dataptr
while remaining > 0:
try:
res = self.send_raw(p, remaining, flags)
p = rffi.ptradd(p, res)
remaining -= res
except CSocketError, e:
if e.errno != _c.EINTR:
raise
if signal_checker is not None:
signal_checker()

看完此段源码,心中应该对send()sendall()有一些认识了

什么时候使用send()什么时候使用sendall()

一般情况下,我们都应该使用sendall(),除非自己弄懂了他们的原理,并且有必要在每次包发送之后进行一些必要的处理,不然我们都不需要去使用send(),而应该使用已经包装好的sendall()

Python中send()和sendall()的区别的更多相关文章

  1. Python中send和sendall的区别

    官方文档对socket模式下的socket.send() 和 socket.sendall()解释如下: sock.sendall(string[, flags]) Send data to the ...

  2. python socket编程入门(编写server实例)+send 与sendall的区别与使用方法

    python 编写server的步骤: 1. 第一步是创建socket对象.调用socket构造函数.如: socket = socket.socket( family, type ) family参 ...

  3. Python中type与Object的区别

    Python中type与Object的区别 在查看了Python的API后,总算明白了.现在总结如下: 先来看object的说明: Python中关于object的说明很少,甚至只有一句话: clas ...

  4. Python中生成器和迭代器的区别(代码在Python3.5下测试):

    https://blog.csdn.net/u014745194/article/details/70176117 Python中生成器和迭代器的区别(代码在Python3.5下测试):Num01–& ...

  5. Python中的is和==的区别,==判断值是否相等,is判断地址是否一致

    Python中的is和==的区别 Python中的对象包含三要素:id.type.value. 其中id用来唯一标示一个对象,type标识对象的类型,value是对象的值. is判断的是a对象是否就是 ...

  6. 基于python中staticmethod和classmethod的区别(详解)

    例子 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 class A(object):   def foo(self,x):     print "executing foo ...

  7. Python中的is和==的区别

    Python中的is和==的区别 1. is 是比较内存地址id() a = "YongJie" b = "YongJie" print(id(a)) #233 ...

  8. python中_new_()与_init_()的区别

    __new__方法的使用 只有继承于object的新式类才能有__new__方法,__new__方法在创建类实例对象时由Python解释器自动调用,一般不用自己定义,Python默认调用该类的直接父类 ...

  9. python中break和continue的区别

    python中break和continue的区别   break和continue 1.break 意思为结束循环   例: i = 0 while i<10:     i+=1     if ...

随机推荐

  1. H5面试题整理

    1.新的HTML5文档类型和字符集是? 文档类型:<!doctype html> 使用UTF-8编码示例:<meta charset="UTF-8"> 2. ...

  2. 基于Cent os 云服务器中SVN 服务器的搭建---具体实践是可行的 一次备注便于后续查找

    https://blog.csdn.net/shadowyingjian/article/details/80588544http://www.hongyanliren.com/2015m04/329 ...

  3. BigDecimal运算(加、减、乘、除)

    public class BigDecimalOperation { private BigDecimalOperation(){ } public static BigDecimal add(dou ...

  4. 魔板 Magic Squares(广搜,状态转化)

    题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 我们知道魔板的每一个方格都有一种颜色.这8种颜 ...

  5. JVM 垃圾回收机制和常见算法和 JVM 的内存结构和内存分配(面试题)

    一.JVM 垃圾回收机制和常见算法 Sun 公司只定义了垃圾回收机制规则而不局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同.GC(Garbage Collector)在回收对象前首先必 ...

  6. 爬虫——使用BeautifulSoup4的爬虫

    我们以腾讯社招页面来做示例:http://hr.tencent.com/position.php?&start=0#a 如上图,使用BeautifulSoup4解析器,将图1中229页,每页1 ...

  7. 你知道JQuery中的事件冒泡吗,他是怎么执行的,如何来停止冒泡事件?

    事件冒泡 首先需要知道什么是事件冒泡? 事件冒泡是从里面的往外面开始触发的,就是点击子节点,会向上触发父节点,祖先节点的点击事件 demo: <html xmlns="http://w ...

  8. PHP无法用下标访问

    php数组分为普通数组和关联数组,普通数组可以用下标访问,而关联数组不可以.

  9. jQuery最重要的知识点

    1.各种常见的选择器.2.对于属性的操作.[重点] 2.1)获取或设置属性的值: prop(); 2.2 ) 添加.删除.切换样式: addClass/removeClass/toggleClass ...

  10. Tornado异步之-协程与回调

    回调处理异步请求 回调 callback 处理异步官方例子 # 导入所需库 from tornado.httpclient import AsyncHTTPClient def asynchronou ...