Многократная передача файлов по постоянному протоколу TCP с использованием Python - PullRequest
0 голосов
/ 23 апреля 2019

Я пытаюсь передать несколько изображений через постоянное TCP-соединение в python. Насколько мне известно, этот код должен работать нормально, но иногда он показывает следующую ошибку ValueError: неверный литерал для int () с основанием 10: '6789:'

Для каждого изображения я сначала пытаюсь отправить размер этого изображения клиенту.

Может кто-нибудь, пожалуйста, помогите мне с тем, что я делаю неправильно, или по-другому подскажите, как это сделать другими способами

Код сервера

import socket                   
import time
import os

port = 6004              
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)             
host = socket.gethostname()     # Get local machine name
s.bind((host, port))            # Bind to the port
s.listen(5)                     # Now wait for client connection.

print ('Server listening....')
conn, addr = s.accept()
print ('Got connection from', addr)
# data = conn.recv(1024)
# print('Server received', repr(data))

start =time.time()

for i in range(2):
    filename="sc" + str(i) + ".jpg"
    size = str(os.path.getsize(filename))
    try:
        conn.send(size.encode())
    except:
        print('ckckckckckck')
    print('filesize', size, len(size))
    f = open(filename,'rb')
    current=0
    size = int(size)
    while current <size:
       l = f.read(1024)
       conn.send(l)
       current+=len(l)
       print('current',current)
       print('l',len(l))
       if(current==size):
        break
    print('close current',current)
    f.close()

print('Done sending')
conn.send(b'Thank you for connecting')
#conn.close()
print(time.time()-start)

Код клиента

import os
import socket 
import time                 # Import socket module

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)             # Create a socket object
host = socket.gethostname()     # Get local machine name
port = 6004               # Reserve a port for your service.

s.connect((host, port))
s.send(b'Hello server!')

for i in range(2):
    data = None
    data = s.recv(1024)
    data = data.decode()
    size = int(data)
    print(size)
    filename = "sc" + str(i) + ".jpg"
    f = open(filename,'wb')
    current =0
    while current<size:
        data = s.recv(1024)
        f.write(data)
        current+=len(data)
        # print('data',len(data))
        # print('current',current)
        if(current==size):
            break
    print('close current',current)
    f.close()
print('Successfully get the file')
s.close()
print('connection closed')

1 Ответ

1 голос
/ 23 апреля 2019
  data = s.recv(5)

Вы ожидаете, что размер находится в пределах первых 5 байтов, и вы ожидаете получить его с одним recv.Но фактический размер может быть меньше 5 байт или более, так как при отправке вы не используете определенное количество байт:

    conn.send(size.encode())

Таким образом, здесь может произойти следующее:Размер, который вы читаете в клиенте, либо слишком мал (если исходный размер был больше), либо размер использовался менее 5 байт, и уже есть данные из содержимого файла в 5 байтах, которые вы прочитали.И это вызывает ошибку, которую вы видите.

Обратите внимание, что TCP является протоколом потока байтов, а не протоколом сообщений, что означает, что то, что вы send, не обязательно то, что вы recv.Вместо этого данные из нескольких send могут быть прочитаны в пределах одного recv, или один send может потребовать нескольких recv.Таким образом, лучший дизайн вашего кода будет гарантировать, что он всегда записывает фиксированную длину для длины и всегда гарантирует, что он получил полную длину, прежде чем пытаться интерпретировать данные как длину.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...