2

我有两个程序,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() 

我相信我在这里陷入了某种僵局,但不知道它是什么。

回答

1

TCP是一个流媒体协议。它没有消息边界的概念。对于阻塞套接字,recv(n)仅在发送方关闭套接字或明确呼叫shutdown(SHUT_WR)时才返回零长度字符串。否则它可以返回一个长度为1到n个字节的字符串,并将阻塞,直到它至少有一个字节返回。

您需要设计一个协议来确定您何时有完整的消息。有几种方法:

  1. 使用固定长度的消息。
  2. 发送一个固定长度的消息,指出消息的总长度,然后发送消息的变量部分。
  3. 发送消息,然后是消息中永远不会发生的唯一终止消息。

您可能会遇到的另一个问题是send()不能保证发送所有数据。返回值表示实际发送了多少字节,并且发送方有责任使用剩余的消息字节继续调用发送,直到它们全部发送完毕。您可以使用sendall()方法。

3

使用阻塞套接字,这是默认的,我假设你正在使用的(不能确定,因为你使用了一个神秘的模块jmm_sockets),recv方法阻塞 - 它不会返回一个正如你似乎假设的那样,“当前没有其他东西可以回报”的时候是空字符串。例如,您可以通过发送一个明确的结束符(绝不会出现在文件名中)来解决此问题,例如, '\xff',在你想要发送的实际字符串之后,并且在另一端等待它作为所有字符串已经被接收的指示。