Python 套接字中的发送和接收是如何工作的?
Posted
技术标签:
【中文标题】Python 套接字中的发送和接收是如何工作的?【英文标题】:How sending and receiving works in Python sockets? 【发布时间】:2014-07-04 23:33:53 【问题描述】:我在使用 python 套接字有一段时间了,我写了一些简单的程序。
我遇到的问题与python sockets中的发送/接收方法有关。 给你一个基本的例子:
这是接收方(服务器):
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('', 4001)) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.listen(5) while True: conn, addr = s.accept() print conn, addr data1 = conn.recv(64) data2 = conn.recv(64) print 'uname is %s , password is: %s' %(data1, data2, ) conn.close()
这是发送者(或客户端):
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('', 4001)) uname = raw_input('enter username>') passw = raw_input('enter password>') s.send(uname) s.send(passw) print 'exiting ...' s.close()
所以问题是:为什么服务器在第一个 s.recv() 方法中同时接收到 uname 和 passw ?这意味着data2总是空的!
我不知道客户端执行s.send()
方法时会发生什么。我在想每个s.send()
实际上都会向目的地(ip、端口)发送一个“数据包”!
有人可以向我解释为什么第二个代码可以正常工作吗?
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('', 4001)) uname = raw_input('enter username>') s.send(uname) passw = raw_input('enter password>') s.send(passw) print 'exiting ...' s.close()
【问题讨论】:
【参考方案1】:socket.SOCK_STREAM
表示您正在通过 TCP 进行通信。这意味着,如果您调用send
,您的数据将被推送到系统的网络堆栈。两个send
调用会一个接一个地调用。
如果您使用 TCP,您的系统将决定数据包的大小。所以uname
和passw
可能会在一个数据包中发送,甚至可以以任何其他方式拆分。
在接收方,data1
最多接收 64 个字节,这对于 uname
和 passw
来说已经足够了。
上面的解释也说明了为什么第二个有效:
在这里,您需要在发送uname
和passw
之间留出一些时间。在此期间,您的操作系统决定发送数据包(即刷新网络缓冲区)。
当您使用流时,您不应考虑数据包,而应考虑流。 send
调用仅意味着:将一些数据推送到我的网络堆栈(如管道)。
如果您对数据包感兴趣, 您可以尝试使用 UDP:
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
使用这种类型的套接字,您的第一个发送者将按预期工作
【讨论】:
真的很有帮助 :) 有没有办法控制“网络缓冲区”?例如在需要时刷新缓冲区。有没有一种好方法可以在 python 中的套接字编程中处理发送和接收?在一个简单框架的某个地方,我读到这样的代码: s = socket(...) s.makefile(rw, 0 ) s.read(64) # 用于接收 s.write(64) # 用于发送 这是更好使用套接字的方法?? 即使有,也只有少数场景需要控制。 TCP 的关键在于它控制数据包是否到达,保持正确的顺序等等。即使您刷新了这个缓冲区,响应者也可能会要求发送者将数据包分成更小的部分。这就是为什么您不应将发送调用视为发送数据包的原因。想象一个流。如果您在 uname 和 password 之间引入分隔符并通过该分隔符拆分您收到的消息,您的具体问题可能会得到解决【参考方案2】:我也遇到了类似的问题。然后我实现了一次发送和接收一条消息的协议。希望此链接对您有很大帮助:LINK
【讨论】:
谢谢(:我猜在这个框架中,link 作者使用了您建议的类似方法(查看 BTPeerConnection 类上的 recvdata 方法)这是一个简单的方法(:以上是关于Python 套接字中的发送和接收是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章