加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
chat_server.py 2.47 KB
一键复制 编辑 原始数据 按行查看 历史
wang.jihong 提交于 2017-12-08 16:42 . add 注释
# coding=utf8
import gevent
from gevent.queue import Queue
from gevent.server import StreamServer
users = {} # 维护所有用户的接受消息对列
def cache(msg):
'''
1) 当一个用户新登陆时,才触发handler:此时是把最后一个登陆者的登陆信息放到其他已经登陆用户的消息队列中;
2)当一个用户发消息时, 不触发handler:此时是把该消息放到所有已经登陆用户的消息队列中,包括本人
'''
msg += '\n'
for v in users.values():
v.put(msg)
def reader(username, f):
"""
读消息,并放到所有用户的接收消息队列中。
登陆时,f没有值; 发消息时才有
"""
for l in f:
msg = '%s> %s' % (username, l.strip())
msg += '\n'
for v in users.values():
v.put(msg)
def writer(q, sock):
"""广播消息"""
while True:
msg = q.get()
print 'id sock: ', id(sock)
sock.sendall(msg)
def read_name(f, sock):
while True:
sock.sendall('Please enter your name: ')
name = f.readline().strip()
if name:
if name in users:
sock.sendall('That username is already taken.\n')
else:
return name
def handle(sock, client_addr):
# 具体信息在f中
f = sock.makefile()
# 只是获得当前哪个用户登陆了,或者哪个用户发的消息
name = read_name(f, sock)
# 把该用户的登陆信息放到别的用户的队列中,或者把改用户发的消息放到其他用户的消息队列
cache('## %s joined from %s.' % (name, client_addr[0]))
q = Queue()
users[name] = q
print 'user %s: ' % name, len(users[name])
# ---------------------------------------------------------#
# ------ 以上代码只会在新用户第一次连接server时执行---------------#
# ------ 所以q并不是上面的空队列,而是reader填充后的队列!!!------#
# ---------------------------------------------------------#
try:
r = gevent.spawn(reader, name, f)
w = gevent.spawn(writer, q, sock)
gevent.joinall([r, w])
print 'not show'
finally:
del (users[name])
cache('## %s left the chat.' % name)
if __name__ == '__main__':
import sys
try:
myip = sys.argv[1]
except IndexError:
myip = '0.0.0.0'
print 'To join, telnet %s 8003' % myip
s = StreamServer((myip, 8003), handle)
s.serve_forever()
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化