Python套接字中的发送和接收是如何工作的?

4 投票
2 回答
3066 浏览
提问于 2025-04-18 06:45

我在用Python做网络编程,已经写了一些简单的程序。

我遇到的问题和Python的socket发送和接收方法有关。给你一个基本的例子:

这是接收端(服务器):

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()时就收到了用户名和密码?这就意味着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()

2 个回答

1

我也遇到过类似的问题。于是我设计了一种协议,可以一次发送和接收一条消息。希望这个链接能对你有很大帮助:链接

2

socket.SOCK_STREAM表示你正在通过TCP进行通信。这意味着,当你调用send时,你的数据会被发送到系统的网络处理部分。而且,如果你连续调用两次send,这两次调用会很快接连发生。

使用TCP时,系统会决定数据包的大小。所以unamepassw可能会在一个数据包中一起发送,也可能会被分开发送。

在接收方,data1最多可以接收64个字节,这对于unamepassw来说是足够的。

上面的解释也说明了为什么第二种方式可以正常工作:

在发送unamepassw之间,你需要留出一些时间。在这段时间里,你的操作系统会决定发送这个数据包(也就是清空网络缓冲区)。

当你使用流的时候,不要把它看作数据包,而是看作数据流。在这里,send的意思只是:把一些数据推送到我的网络处理部分(就像一个管道)。

如果你对数据包感兴趣,可以尝试使用UDP进行实验:

socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

使用这种类型的套接字,你的第一个发送者将会按预期工作。

撰写回答