【问题标题】:Why is this input being over lapped by another input?为什么这个输入被另一个输入重叠?
【发布时间】:2018-07-27 03:30:34
【问题描述】:

我在 Python 2.7.10 中创建了一个 TCP 服务器,一旦我输入了我的用户名,它就意味着要求输入密码,而不是说

用户名:管理员

密码:管理员

它说

用户名:管理员

密码:昵称:

昵称是密码后面的输入 以下是相关代码:

    def username(conn, prefix="Username: "):
        conn.send(prefix)
        return conn.recv(512)

    def password(conn, prefix="Password: "):
        conn.send(prefix)
        return conn.recv(512)

    def nickname(conn, prefix="Nickname: "):
        conn.send(prefix)
        return conn.recv(512)

    username = username(conn)
    password = password(conn)
    nickname = nickname(conn)

有什么问题?

【问题讨论】:

  • 你能粘贴完整的代码你如何创建连接
  • 那部分与输入无关

标签: python sockets


【解决方案1】:

您不会显示连接另一端发生的情况。但是,我很确定问题在于您没有正确区分收到的不同消息的边界。例如,假设一方执行以下操作:

s.send('Hello')
s.send('Again')
s.send('Once More')

当对方执行时:

first = s.recv(512)
second = s.recv(512)
third = s.recv(512)

这里很可能发生的情况是,第一个recv 将接收所有三个数据块('HelloAgainOnce More'),然后接收方将挂在第二个recv 等待发送系统发送更多数据。但请注意,第一个recv 得到'Hel',第二个recv 得到'l',第三个得到@987654330,这也是可能 - 并且根据套接字API 有效@ 并且剩余的字节被留在某处传输(最终在接收系统的内核缓冲区中排队)。还有许多其他可能的结果。

这里的重点是在使用 TCP 流套接字时必须提供自己的消息边界。 TCP 将数据从一个对等点传递到另一个对等点的recv 调用不保证应用程序打算遵守的任何边界,而且通常不会。

区分消息边界的常用方法有两种:

  1. 对于“基于文本”的协议,某些分隔符(例如换行符或空字节)用于分隔消息。像 HTTP 这样的协议使用它。在 python 中,这通常是这样完成的:首先recv将数据放入缓冲区,然后提取其中的一部分,直到找到消息分隔符(如果找不到分隔符,则返回recv更多)。

  2. 对于二进制协议,该协议为每个数据块提供明确的长度字段。在 python 中,这通常涉及使用struct 模块,它允许您构造包含整数和其他特定大小的数值的二进制字段。然后一次接收(或从缓冲区消耗)确切字节数的消息(再次返回recv,直到获得给定消息所需的所有字节)。

(我应该提一下,在技术上可能send 不会发送其整个参数:在某些情况下,当您执行s.send('Hello') 时,仅发送'H' . 您可以通过使用sendall 方法来解决这个问题,该方法只是继续send,直到提供的数据的所有部分都已传输。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    • 2021-05-06
    • 2022-12-22
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 2018-08-26
    相关资源
    最近更新 更多