【问题标题】:Python Socket - last symbol is missingPython Socket - 最后一个符号丢失
【发布时间】:2021-12-13 04:26:45
【问题描述】:

所以,我创建了客户端和服务器端 sing socket。
一切正常,但我刚刚使用 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。 我不知道为什么会这样。我已经尝试使用数据库中的不同表并更改缓冲区大小,但它仍然在某个地方吃这个和平。 服务器中有两个打印件。首先显示接收时使用的缓冲区。第二个用于显示它实际接收到的符号数量,它始终有效,但不适用于该字符串。

如果我在这里没有涵盖某些内容或一些重要信息,请在评论中写下,我会提供。

【问题讨论】:

  • conn.recv() 可以返回比您要求的少,除非您使用 MSG_WAITALL 标志。
  • 虽然@Barmar 是正确的,但这不是您的问题的原因。问题是您的生产字符串包含非 ASCII 字符。因此,尽管 Unicode 中的字符串是 1481 个字符,而这正是您嵌入的,但当它被转换为 UTF-8 进行传输时,生成的字符串长度为 1482 个字节。您需要在计算长度之前转换为 UTF-8。
  • @TimRoberts 感谢您的更正。您应该将其发布为答案。

标签: python python-3.x sockets


【解决方案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)

【讨论】:

  • 那,行得通!谢谢你,但是[:30] 是做什么的?
  • 表示“取前 30 个字符”。与其麻烦计算要添加多少#,我只需添加 30 并在 30 处截断结果字符串。
猜你喜欢
  • 1970-01-01
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多