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',在你想要發送的實際字符串之後,並且在另一端等待它作爲所有字符串已經被接收的指示。