[英]Python socket error - recv() function
我一直在尝试用Python编写一个简单的聊天服务器,我的代码如下:
import socket
import select
port = 11222
serverSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1024)
serverSocket.bind(('',port))
serverSocket.listen(5)
sockets=[serverSocket]
print 'Server is started on port' , port,'\n'
def acceptConn():
newsock, addr = serverSocket.accept()
sockets.append(newsock)
newsock.send('You are now connected to the chat server\n')
msg = 'Client joined',addr.__str__(),
broadcast(msg, newsock)
def broadcast(msg, sourceSocket):
for s in sockets:
if (s != serverSocket and s != sourceSocket):
s.send(msg)
print msg,
while True:
(sread, swrite, sexec)=select.select(sockets,[],[])
for s in sread:
if s == serverSocket:
acceptConn()
else:
msg=s.recv(100)
if msg.rstrip() == "quit":
host,port=socket.getpeername()
msg = 'Client left' , (host,port)
broadcast(msg,s)
s.close()
sockets.remove(s)
del s
else:
host,port=s.getpeername()
msg = s.recv(1024)
broadcast(msg,s)
continue
运行服务器并通过telnet连接后,服务器读取单个字符并跳过下一个字符。 例如,如果我在telnet中键入Hello,则服务器读取H10。 有什么帮助吗?! :)
您两次调用recv。
第一:
msg=s.recv(100)
然后,如果不是“退出”,则您阅读并广播了另一条消息:
msg = s.recv(1024)
broadcast(msg,s)
因此,原始消息丢失了。
因为您使用telnet作为客户端,所以一次只能获得一个字符,因此您可以看到其他所有字符。 如果使用nc代替,则会得到不同的结果,但是其他所有读操作都将被丢弃,这是相同的基本问题。
这里还有其他一些问题:
这是示例的修改后的版本,它解决了大多数问题,除了要求“退出”仅包含在一条消息中并依靠客户端发送换行符之外:
#!/usr/bin/python
import socket
import select
import sys
port = 11222
serverSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1024)
serverSocket.bind(('',port))
serverSocket.listen(5)
sockets=[serverSocket]
print 'Server is started on port' , port,'\n'
def acceptConn():
newsock, addr = serverSocket.accept()
sockets.append(newsock)
newsock.send('You are now connected to the chat server\n')
msg = 'Client joined: %s:%d\n' % addr
broadcast(msg, newsock)
def broadcast(msg, sourceSocket):
for s in sockets:
if (s != serverSocket and s != sourceSocket):
s.send(msg)
sys.stdout.write(msg)
sys.stdout.flush()
while True:
(sread, swrite, sexec)=select.select(sockets,[],[])
for s in sread:
if s == serverSocket:
acceptConn()
else:
msg=s.recv(100)
if not msg or msg.rstrip() == "quit":
host,port=s.getpeername()
msg = 'Client left: %s:%d\n' % (host,port)
broadcast(msg,s)
s.close()
sockets.remove(s)
del s
else:
host,port=s.getpeername()
broadcast(msg,s)
continue
要解决“退出”问题,您将必须为每个客户端保留一个缓冲区,并执行以下操作:
buffers[s] += msg
if '\nquit\n' in buffers[s]:
# do quit stuff
lines = buffers[s].split('\n')[-1]
buffers[s] = ('\n' if len(lines) > 1 else '') + lines[-1]
但是您仍然遇到换行问题。 假设用户1登录并键入“ abc \\ n”,而用户2登录并键入“ def \\ n”; 您可能会得到类似“ abClient加入:127.0.0.1:56881\\ndec\\nf\\n”的信息。
如果需要基于行的协议,则必须重写代码以逐行而不是逐读地执行回显。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.