Python сокет: сервер «получает» больше размера буфера даже после завершения работы клиента - PullRequest
0 голосов
/ 13 февраля 2020

Это мой первый вопрос о переполнении стека, надеюсь, я правильно понял.

Я пытаюсь работать с Python сокетами и использую базовый c клиент и сервер эхо. Клиент отправляет некоторые данные на сервер, сервер печатает их и отправляет обратно, клиент печатает их и закрывает, сервер должен закрыться.

В попытке попробовать отправить разные типы данных (другая история) я столкнулся с проблемой, которую не могу объяснить. На клиенте я генерирую строку больше 1024 и отправляю ее на сервер, который только recv (1024), сервер должен распечатать данные, распечатать их длину и отправить обратно. Вместо этого сервер печатает данные и длину, отправляет их обратно, после чего клиент завершает работу, как ожидалось, но сервер продолжает печатать данные и длину еще два раза. Почему это l oop продолжается? Если в буфере более 1024 байтов, не должны ли они быть отброшены? Или «следующие» 1024 байта будут в «данных», и l oop будет продолжаться, пока все данные не будут обработаны и напечатаны?

Я затрудняюсь объяснить, почему это происходит, не должен ли l oop на сервере прекратиться, когда соединение с клиентом разорвано? Кажется, что сервер получает несколько раз, но клиент отправляет только один раз, поэтому я думаю, что это может быть связано с размером буфера? Любая помощь приветствуется. Код ниже.

Клиент

  1  #!/usr/bin/env python3
  2
  3 import socket
  4 import random
  5
  6
  7 HOST = '127.0.0.1'
  8 PORT = 5099
  9
 10 def create_string(s):
 11     for x in range(1, 10):
 12         s = s + s
 13     return s
 14
 15 msg = create_string("Example ")
 16 print(len(msg))
 17
 18 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
 19     s.connect((HOST, PORT))
 20
 21     s.send(msg.encode())
 22     data = s.recv(1024)
 23
 24     print('Received ', repr(data))

Сервер:

1 #!/usr/bin/env python3
  2
  3 import socket
  4 import time
  5
  6 HOST = '127.0.0.1' # Localhost address
  7 PORT = 5099
  8
  9 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
 10     s.bind((HOST, PORT))
 11     s.listen()
 12     conn, addr = s.accept()
 13     with conn:
 14
 15
 16         print('Connected by', addr)
 17         while True:
 18
 19             data = conn.recv(1024)
 20             print(data.decode())
 21             print(len(data))
 22             time.sleep(2)
 23             if not data:
 24                 break
 25             conn.send(data) # send and sendall() give same result.
 26             time.sleep(1)

Я добавил несколько спящих функций, чтобы посмотреть, что происходит, а также попытался пройти через pdb.

Вот скриншот того, как это заканчивается. Клиент завершает работу после первой функции печати на сервере.

снимок экрана

1 Ответ

0 голосов
/ 13 февраля 2020

Сокет TCP - это поток байтов. Вы получите столько же байтов в том же порядке, что и отправленные. Размер recv(n) не имеет значения. Вы получите 0 (если сокет закрывается) или от 1 до n байтов. Вам не гарантировано получение количества запрошенных байтов, и они не гарантируют, что они будут разбиты так же, как они были отправлены.

Вы несете ответственность за понимание потока байтов. Буферизуйте полученные данные, пока не получите полное сообщение. Вы определяете, когда означает полное сообщение.

Кроме того, send() также не гарантирует отправку всех запрошенных вами байтов. Проверьте возвращаемое значение и повторно отправьте часть буфера, который не отправлял или не использовал sendall().

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