插座交互期间的程序悬挂
-
04-10-2019 - |
题
我有两个程序,即sendfile.py和recvfile.py,它们应该交互以在整个网络上发送文件。他们通过TCP插座进行通信。沟通应该这样做:
sender =====filename=====> receiver
sender <===== 'ok' ======= receiver
or
sender <===== 'no' ======= receiver
if ok:
sender ====== file ======> receiver
我有
发件人和接收器代码在这里:
发件人:
import sys
from jmm_sockets import *
if len(sys.argv) != 4:
print "Usage:", sys.argv[0], "<host> <port> <filename>"
sys.exit(1)
s = getClientSocket(sys.argv[1], int(sys.argv[2]))
try:
f = open(sys.argv[3])
except IOError, msg:
print "couldn't open file"
sys.exit(1)
# send filename
s.send(sys.argv[3])
# receive 'ok'
buffer = None
response = str()
while 1:
buffer = s.recv(1)
if buffer == '':
break
else:
response = response + buffer
if response == 'ok':
print 'receiver acknowledged receipt of filename'
# send file
s.send(f.read())
elif response == 'no':
print "receiver doesn't want the file"
# cleanup
f.close()
s.close()
接收者:
from jmm_sockets import *
s = getServerSocket(None, 16001)
conn, addr = s.accept()
buffer = None
filename = str()
# receive filename
while 1:
buffer = conn.recv(1)
if buffer == '':
break
else:
filename = filename + buffer
print "sender wants to send", filename, "is that ok?"
user_choice = raw_input("ok/no: ")
if user_choice == 'ok':
# send ok
conn.send('ok')
#receive file
data = str()
while 1:
buffer = conn.recv(1)
if buffer=='':
break
else:
data = data + buffer
print data
else:
conn.send('no')
conn.close()
我敢肯定,我在僵局中错过了一些东西,但不知道这是什么。
解决方案
TCP是流媒体协议。它没有消息边界的概念。对于阻塞插座, recv(n)仅当发件人关闭套接字或明确调用时,才会返回零长度的字符串 关闭(shut_wr)。否则,它可以返回一个字符串的长度为n字节,并将阻止至少一个字节返回。
您必须设计一个协议来确定何时有完整的消息。几种方法是:
- 使用固定长度消息。
- 发送指示总消息长度的固定长度消息,然后发送消息的可变部分。
- 发送消息,然后发送唯一的终止消息,该消息将在消息中永远不会发生。
您可能面临的另一个问题是 发送()不能保证发送所有数据。返回值表示实际发送了多少个字节,发件人的责任是继续使用剩余的消息字节发送到全部发送。您可能宁愿使用 全部发送() 方法。
其他提示
带有阻塞插座,这是默认值,我认为您是您正在使用的(不能确定,因为您使用了一个神秘的模块 jmm_sockets
), 这 recv
方法正在阻止 - 当您似乎假设“目前无需返回”时,它不会返回一个空字符串。
例如,您可以通过发送显式终结者字符(绝不会在文件名中发生)来解决此问题,例如 '\xff'
, ,在您要发送的实际字符串之后,并在另一端等待它,以表明现在已收到所有字符串。
不隶属于 StackOverflow