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,您的系统将决定数据包的大小。所以unamepassw 可能会在一个数据包中发送,甚至可以以任何其他方式拆分。

在接收方,data1 最多接收 64 个字节,这对于 unamepassw 来说已经足够了。

上面的解释也说明了为什么第二个有效:

在这里,您需要在发送unamepassw 之间留出一些时间。在此期间,您的操作系统决定发送数据包(即刷新网络缓冲区)。

当您使用流时,您不应考虑数据包,而应考虑流。 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 套接字中的发送和接收是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

同时发送/接收消息套接字python

在做其他工作的同时通过 python 接收消息

iOS 上的 Objective-C 套接字发送和接收

Python 3套接字客户端发送数据和C++套接字服务器接收偏移数据?

Python Socket - 同时发送/接收消息

如何通过套接字发送/接收二进制数据?