2

sendfile.py と recvfile.py という 2 つのプログラムがあり、ネットワーク経由でファイルを送信するために相互作用するはずです。それらは 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()

ここでデッドロックのようなものを見逃していると確信していますが、それが何であるかはわかりません。

4

2 に答える 2

3

デフォルトであり、あなたが使用しているものであると私は推測しているブロッキングソケットを使用すると(不思議なモジュールを使用しているため、確信が持てませんjmm_sockets)、recvメソッドはブロックされています-「あなたが想定しているように、今のところ戻るものは何もありません。

たとえば、明示的なターミネータ文字 (ファイル名内に出現してはならない) を送信することで、これを回避できます。たとえば、送信する'\xff'実際の文字列の後に、すべての文字列が受信されました。

于 2010-05-25T01:09:21.413 に答える
2

TCP はストリーミング プロトコルです。メッセージ境界の概念はありません。ブロッキング ソケットの場合、 recv (n) は、送信者がソケットを閉じた場合、または明示的にシャットダウン(SHUT_WR) を呼び出した場合にのみ、長さ 0 の文字列を返します。それ以外の場合は、長さが 1 ~ n バイトの文字列を返すことができ、少なくとも 1 バイトを返すまでブロックします。

完全なメッセージがいつ得られるかを判断するためのプロトコルを設計するのは、開発者次第です。いくつかの方法は次のとおりです。

  1. 固定長メッセージを使用します。
  2. メッセージの合計長を示す固定長メッセージを送信し、その後にメッセージの可変部分を送信します。
  3. メッセージを送信し、その後にメッセージ内で発生しない一意の終了メッセージを送信します。

直面する可能性のある別の問題は、send () がすべてのデータを送信するとは限らないことです。戻り値は、実際に送信されたバイト数を示します。すべて送信されるまで、残りのメッセージ バイトを使用して send を呼び出し続けるのは送信者の責任です。sendall () メソッドを使用することもできます。

于 2010-05-25T05:59:01.847 に答える