我已经在Python 2.7.10中制作了一个TCP Server,一旦输入用户名,就要求输入密码,而不是说
用户名:管理员
密码:管理员
说
用户名:管理员
密码:昵称:
昵称是密码后的输入 这是相关代码:
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)
出了什么问题?
答案 0 :(得分:0)
您没有显示连接另一端正在发生的情况。但是,我很确定问题是您没有正确地区分收到的不同邮件的边界。例如,假设一侧执行此操作:
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
获得{{1 }},第三个获取'l'
,其余字节留在传输中的某个地方(最终在接收系统的内核缓冲区中排队)。还有许多其他可能的结果。
这里的重点是,在使用TCP流套接字时必须提供自己的消息边界。 TCP从一个对等方传送流数据。 'o'
调用不能保证应用程序预期的任何边界,而且通常不会。
通常有两种区分消息边界的方法:
对于“基于文本的”协议,某些分隔符(例如换行符或空字节)分隔消息。 HTTP等协议使用此协议。在python中,通常是先将数据recv
放入缓冲区,然后再将其拉出直到找到消息分隔符(如果找不到分隔符,请再回到recv
来完成此操作) )。
对于二进制协议,该协议为每个数据块提供了显式的长度字段。在python中,这通常涉及使用recv
模块,该模块允许您构造包含整数和特定大小的其他数值的二进制字段。然后一次接收精确字节数的消息(或从缓冲区消耗)(再次返回struct
,直到获得给定消息所需的所有字节为止)。
(我应该指出,recv
在技术上也是 可能没有发送其整个参数:在某些情况下,当您执行send
时,仅{ {1}}已发送。您可以使用s.send('Hello')
方法来解决,该方法只继续'H'
直到提供的数据的所有部分都已传输。)