#python-3.x #sockets
#python-3.x #сокеты
Вопрос:
Я пытаюсь передать несколько изображений по постоянному TCP-соединению на Python. Насколько мне известно, этот код должен работать нормально, но иногда он показывает следующее значение ошибки ERROR: недопустимый литерал для 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:
data = s.recv(5)
Вы ожидаете, что размер находится в пределах первых 5 байтов, и вы ожидаете получить его с помощью одного recv
. Но фактический размер может быть меньше 5 байт или более, поскольку вы не применяете определенное количество байтов при отправке:
conn.send(size.encode())
Таким образом, здесь может произойти то, что размер, который вы читаете в клиенте, либо слишком мал (если исходный размер был больше), либо размер, используемый менее 5 байт, и в 5 байтах, которые вы читаете, уже есть данные из содержимого файла. И это вызывает ошибку, которую вы видите.
Обратите внимание, что TCP — это протокол байтового потока, а не протокол сообщений, что означает, что то, что вы send
, не обязательно то, что вы recv
. Вместо этого данные из нескольких send
могут быть прочитаны в пределах одного recv
, или для одного send
может потребоваться несколько recv
. Таким образом, лучший дизайн вашего кода должен гарантировать, что он всегда записывает фиксированную длину для длины и всегда проверяет, что он получил полную длину, прежде чем пытаться интерпретировать данные как длину.
Комментарии:
1. извините, что data = s.recv(5) записан по ошибке. Но на самом деле происходит то, что два вызова send объединяются и возвращают одно чтение, не могли бы вы помочь, как я могу это решить
2. @siddharthshrivastava: цитирую себя: «… TCP — это протокол байтового потока, а не протокол сообщений, что означает, что то, что вы отправляете, не обязательно является тем, что вы recv …» и «… лучший дизайн вашего кода гарантировал бы, что он всегда записывает фиксированную длину для длины и всегда гарантирует, что он получил полную длину , прежде чем пытаться интерпретировать данные как длину «.
3. Итак, если я использую UDP вместо TCP, будет ли решена эта проблема. но когда я попытался с udp, один recvfrom возвращает данные из multiple send () можете ли вы, пожалуйста, помочь мне с этим, я действительно хочу отправить несколько изображений с сервера на клиент, есть ли другой способ сделать это.
4. @siddharthshrivastava: Я явно выделил соответствующие моменты в своем комментарии. Мне непонятно, чего вы не понимаете, поскольку вы даже не обращаетесь ни к чему, что я сказал. Вместо этого вы просто просите о помощи, не сообщая, где именно вам нужна помощь.