Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么这个输入被另一个输入重叠?_Python_Sockets - Fatal编程技术网

Python 为什么这个输入被另一个输入重叠?

Python 为什么这个输入被另一个输入重叠?,python,sockets,Python,Sockets,我已经在Python2.7.10中创建了一个TCP服务器,一旦我输入用户名,它就意味着询问密码,而不是说 用户名:Admin 密码:Admin 上面说 用户名:Admin 密码:昵称: 昵称是密码后的输入 以下是相关代码: def username(conn, prefix="Username: "): conn.send(prefix) return conn.recv(512) def password(conn, pre

我已经在Python2.7.10中创建了一个TCP服务器,一旦我输入用户名,它就意味着询问密码,而不是说

用户名:Admin

密码:Admin

上面说

用户名:Admin

密码:昵称:

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

    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)

问题是什么?

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

s.send('Hello')
s.send('Again')
s.send('Once More')
而另一方执行:

first = s.recv(512)
second = s.recv(512)
third = s.recv(512)
这里很可能发生的情况是,第一个
recv
将接收所有三个数据块(
'helloagaiance More'
),然后接收方将挂起第二个
recv
,等待发送系统发送更多数据。但是请注意,根据套接字API,第一个
recv
获取
'Hel'
,第二个
recv
获取
'l'
和第三个获取
'o'
也是可能的,并且剩余的字节留在传输过程中的某个地方(最终在接收系统的内核缓冲区中排队)。还有许多其他可能的结果

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

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

  • 对于“基于文本”的协议,某些分隔符(如换行符或空字节)用于分隔消息。像HTTP这样的协议就是这样使用的。在python中,这通常是通过首先
    recv
    将数据放入缓冲区,然后从中取出位,直到找到消息分隔符(如果没有找到分隔符,则返回到
    recv
    更多)

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


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

    您可以粘贴完整的代码吗?如何创建连接该部分与输入无关