#python #python-3.x #sockets
Вопрос:
Итак, я создал клиентский и серверный сокет sing.
И все работает хорошо, но я просто сломался, используя строку из базы данных MySQL.
Сервер:
import socket import threading PORT = 9696 SERVER = "localhost" ADDR = (SERVER, PORT) FORMAT = 'utf-8' server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(ADDR) def handle_client(conn): while True: actual_size = int(conn.recv(30).decode(FORMAT).replace("#", "")) size = int(actual_size / 1024) rest_msg = actual_size - (size * 1024) received_message = "" for chunk in range(size): received_message = conn.recv(1024).decode(FORMAT) received_message = conn.recv(rest_msg).decode(FORMAT) print(rest_msg) print(len(received_message)) def start(): server.listen() while True: conn, addr = server.accept() thread = threading.Thread(target=handle_client, args=(conn,)) thread.start() start()
Клиент:
import socket import time HEADER = 64 PORT = 9696 FORMAT = 'utf-8' SERVER = "localhost" ADDR = (SERVER, PORT) client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(ADDR) def send(msg): client.send(msg.encode("utf-8")) msg_to_send = "Some random message" time.sleep(3) for i in range(1000): send(str(len(msg_to_send)) ("#" * (30 - len(str(len(msg_to_send)))) msg_to_send)) while True: pass
Если я msg_to_send
заменю следующим текстом:
[('index', 'bigint(20)', 'YES', 'MUL', None, ''), ('LP', 'text', 'YES', '', None, ''), (' NR-a', 'text', 'YES', '', None, ''), ('LITERA-a', 'text', 'YES', '', None, ''), ('MUFA-a', 'double', 'YES', '', None, ''), ('UWAGI-a', 'text', 'YES', '', None, ''), ('TUBY-a', 'double', 'YES', '', None, ''), ('DATA1-a', 'text', 'YES', '', None, ''), ('DATA2-a', 'text', 'YES', '', None, ''), ('SPAWY-i', 'text', 'YES', '', None, ''), ('SPAWY_DAC-i', 'text', 'YES', '', None, ''), ('LOG-a', 'text', 'YES', '', None, ''), ('SPLIT1X4-i', 'text', 'YES', '', None, ''), ('SPLIT1X8-i', 'text', 'YES', '', None, ''), ('SPLIT1X16-i', 'text', 'YES', '', None, ''), ('ADAPTERY SIMPLE-i', 'double', 'YES', '', None, ''), ('ADAPTERY DUPLEX-i', 'double', 'YES', '', None, ''), ('PIGTAIL-i', 'double', 'YES', '', None, ''), ('OLT-a', 'double', 'YES', '', None, ''), ('NEXT-a', 'double', 'YES', '', None, ''), ('ODNOGA_1-a', 'double', 'YES', '', None, ''), ('ODNOGA_2-a', 'double', 'YES', '', None, ''), ('ODNOGA_3-a', 'double', 'YES', '', None, ''), ('ODNOGA_4-a', 'double', 'YES', '', None, ''), ('DROP30-i', 'double', 'YES', '', None, ''), ('DROP50-i', 'double', 'YES', '', None, ''), ('DROP70-i', 'double', 'YES', '', None, ''), ('DROP80-i', 'double', 'YES', '', None, ''), ('DROP100-i', 'double', 'YES', '', None, ''), ('DROP120-i', 'double', 'YES', '', None, ''), ('DROP150-i', 'double', 'YES', '', None, ''), ('DROP200-i', 'double', 'YES', '', None, ''), ('MAŁPKI-i', 'double', 'YES', '', None, '')]
И это потеряно ]
, поэтому следующее сообщение, если оно будет преобразовано в int, чтобы оно могло прочитать, как долго будет следующее сообщение, оно просто выдаст ошибку, например ]6
, str. Я понятия не имею, почему это происходит. Я попробовал использовать другую таблицу из базы данных и изменил размер буфера, но она все еще где-то ест этот мир. И на сервере есть два отпечатка. Сначала покажите буфер, который использовался при получении этого. И второй для отображения того, сколько символов он на самом деле получил, и он всегда работает, но не с этой строкой.
Если я не осветил здесь что-то или какую-то важную информацию, пожалуйста, напишите в комментарии, и я предоставлю ее.
Комментарии:
1.
conn.recv()
может вернуть меньше, чем вы просите, если вы не используетеMSG_WAITALL
флаг.2. Хотя @Barмар прав, это не причина вашей проблемы. Проблема в том, что ваша рабочая строка содержит символ, отличный от ASCII. Таким образом, хотя строка в Юникоде состоит из 1481 символа, и это то, что вы вставляете, когда она преобразуется в UTF-8 для передачи, результирующая строка имеет длину 1482 байта. Вам нужно преобразовать в UTF-8, прежде чем вычислять длину.
3. @TimRoberts Спасибо за исправление. Вы должны опубликовать это в качестве ответа.
Ответ №1:
Ваша проблема в том, что ваша рабочая строка содержит символ, отличный от ASCII, и он преобразуется в несколько байтов при кодировании в UTF-8. Эти несколько байтов не учитываются при передаче длины. Вам нужно захватить длину ПОСЛЕ преобразования. Итак, избавьтесь от функции «отправить» и сделайте:
msg_to_send = msg_to_send.encode('utf-8') for i in range(1000): print(len(msg_to_send)) prefix = (str(len(msg_to_send)) "#"*30)[:30].encode('utf-8') client.send(prefix msg_to_send) while True: time.sleep(5)
Комментарии:
1. Это работает! Спасибо вам, но что же
[:30]
делает?2. Там написано «возьмите первые 30 символов». Вместо того, чтобы утруждать себя вычислением того, сколько # нужно добавить, я просто добавляю 30 и обрываю полученную строку на 30.