ZinBu
@ZinBu
Продам гараж (в лс)

Почему модуль socket в python обрезает данные при приеме независимо от параметра в функции recv?

Здравствуйте!
Есть скрипт сервер и скрипт клиент, обменивающиеся данными через socket. Подключены через роутер. Проблема в том, что на Windows клиент работает нормально, а тот же клиентский код на ubuntu, независимо от параметра функции recv, обрезает данные, которые отправляются с сервера! Причем изменение с recv(1024), например на recv(8192) не дает никаких изменений, куски одного и того же размера приходят.
Данных отсылается примерно на 17 kB.

Есть еще две оговорки:
1) на винде возникает та же проблема, если подключить клиентский компьютер не через кабель к роутеру, а через wi-fi.
А если через кабель, то все отлично! Сервер в обоих случаях соединен с роутером по wi-fi.
При этот на ubuntu такая проблема всегда.

2) клиент является частью GUI приложения реализованном на pyqt, не думаю, что в этом дело, но все же...

Клиент:
def exchange_data(self, a, timeout=None):
        """Send commands to server and receive the answer from it"""

        host = self.open_config()
        port = 9090
        
        gateway = socket.socket()
        gateway.settimeout(timeout)  # set response timeout
        gateway.connect((host, port))
        gateway.send(bytes(a, encoding = "utf-8"))

        data = gateway.recv(1024)
        log = gateway.recv(32768)     # именно этот кусок данных независимо от параметра обрезается на ubuntu
        gateway.close()
        return data, log


Сервер:
port = 9090
sock = socket.socket()
# create a socket
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # reuse a local socket if it busy
sock.bind(('', port))  

while True:
    print('Receiving...')
    sock.listen(1)
    conn, addr = sock.accept()
    try:
        data = conn.recv(1024)
        print("recive data: ", data)
        # welcome
        if data == b"conn":
            conn.send(b'ok')
            conn.close()
        
        elif data == b"some_command":
            os.system("python script.py {}".format(data.decode("utf-8")))   # decode a byte to string in command
            # send data when it appear
            while True:
                # send values
                with open("values", "rb") as f:
                    values= f.read()
                    if len(values) > 3:
                        conn.send(values)
                        # send other values
                        with open("other_values", "rb") as lg:
                            log = lg.read()
                            if len(log) > 3:
                                conn.send(log)
                                conn.close()
                                break
    except Exception:
        continue
  • Вопрос задан
  • 1168 просмотров
Решения вопроса 1
leahch
@leahch
3D специалист. Dолго, Dорого, Dерьмово.
Просто вы неправильно эти данные принимаете. Если посмотреть описание функции recv, то она возвращает реально принятые данные, которые могут быть порезаны. В вашем случае нужно в цикле принимать данные, пока не будет достигнута нужная длина. А еще лучше, сделать заголовок, в котором будет храниться длина пакета, сначала принимаете заголовок, потом в цикле принимаете данные на нужную длину. Tcp гарантирует, что данные не перемешаются и будут приходить последовательно, но протокол не гарантирует, что данные будут приходить ровно теми же самыми кусками, которыми они были отправлены.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы