Вопрос

У меня есть две программы, 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 BYTES по длине и заблокирует, пока у нее не будет, по крайней мере, один байт, чтобы вернуться.

Вам решать разработать протокол, чтобы определить, когда у вас есть полное сообщение. Несколько способов:

  1. Используйте сообщение фиксированной длины.
  2. Отправьте сообщение фиксированной длины, указывающее на полную длину сообщения, а затем переменная часть сообщения.
  3. Отправьте сообщение, а затем уникальное сообщение о прекращении, которое никогда не возникнет в сообщении.

Другой вопрос, который вы можете столкнуться, это то, что Отправить() не гарантируется отправлять все данные. Возвращаемое значение указывает на то, насколько фактически отправлены байты, и это ответственность отправителя, чтобы продолжать звонить отправить с оставшимся байтами сообщений, пока они не будут отправлены. Вы предпочитаете использовать отправьте все() Метод.

Другие советы

С блокирующими розетками, которые имеют значение по умолчанию, и я предполагаю, что вы используете (не можете быть уверены, так как вы используете загадочный модуль jmm_sockets), то recv Метод блокирует - он не будет возвращать пустую строку, когда она имеет «ничего больше, чтобы вернуться на данный момент», как вы, кажется, предполагаете.

Вы можете работать вокруг этого, например, путем отправки явного символа терминатора (который никогда не должен происходить в именем файле), например '\xff', После фактической строки вы хотите отправить и ждать его на другом конце в качестве указания, что вся строка теперь была получена.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top