python实现虚拟茶话会

这个项目目的是编写一个聊天服务器,该聊天服务器的功能有:

服务器能同时接收来自不同用户的连接

允许用户同时操作

能够解释命令,例如,say或者logout命令

服务器容易扩展

这个项目里面我们会使用到的模块式asyncore,使用asyncore框架,程序可以处理同时连接多个用户。asyncore框架基于一些底层的机制,这些机制允许服务器逐个的对于连接上的用户进行服务。在处理下一个连接前,它并不读取当前用户的所有可用数据,而只读取一部分。除此之外,服务器只从那些需要读取数据的套接字中读取。程序就这样一遍遍的循环。写入操作同理。只使用socket和select模块就可以实现,但是asyncore和asynchat提供了一个可以处理所有细节的有用框架。

首先我们需要一个客户端来测试服务器,在windows下我们可以用telnet服务端,在unix内也可以用telnet。

初次实现:

首先我们需要创建两个类:一个作为聊天服务器,一个用于表示每个聊天会话(以连接用户)

要生成基本的ChatServer类,需要继承asyncore模块中的dispatcher类,dispatcher基本上就是一个套接字对象,但是可以利用它额外的事件处理特性。

下面是可以接受连接的服务器代码

 1 from asyncore import dispatcher
 2 import socket, asyncore
 3
 4 class ChatServer(dispatcher):
 5     def handle_accept(self):
 6         conn, addr = self.accept()
 7         print ‘Connection attempt from ‘,addr[0]
 8
 9 s = ChatServer()
10 s.create_socket(socket.AF_INET, socket.SOCK_STREAM)
11 s.bind((‘‘.5005))
12 s.listen(5)
13 asyncore.loop()

handle_accpet方法会调用允许客户端连接的self.accept函数。她会返回一个连接和一个地址。handle_accept方法知识打印有关连接尝试的信息。

当我们运行这个服务器并且用客户端连接他的时候,我们可以再服务器的控制台上看到返回的连接信息。

ChatSession类的主要任务是为每一个连接创建一个对象,该对象负责收集来自客户端的数据并且进行响应。我们可以自己继承dispatcher并且重写一些方法来实现这个功能,但是幸运的是已经有现成的模块能够完成绝大多数的工作,asynchat

下面便是一个简单的聊天服务器

 1 # -*- coding:utf-8 -*-
 2 ‘‘‘
 3 xianghang
 4 2015.4.9
 5 虚拟聊天室
 6 ‘‘‘
 7
 8 from asyncore import dispatcher
 9 from asynchat import async_chat
10 import socket, asyncore
11
12 PORT = 5005
13 NAME = ‘TestChat‘
14 class ChatSessioin(async_chat):
15     ‘‘‘
16     处理服务器和一个用户之间连接的类
17     ‘‘‘
18     def __init__(self, server, sock):
19         #标准设置任务
20         async_chat.__init__(self, sock)
21         self.server = server
22         self.set_terminator(‘\r\n‘)
23         self.data = []
24         #问候用户
25         self.push(‘Welcome to %s\r\n‘ % self.server.name)
26
27     def collect_incoming_data(self, data):
28         self.data.append(data)
29
30     def found_terminator(self):
31         ‘‘‘
32         如果发现了一个终止对象,也就意味着读入了一个完整的行,将广播给所有人
33         ‘‘‘
34         line = ‘‘.join(self.data)
35         self.data = []
36         self.server.broadcast(line)
37
38     def handle_close(self):
39         async_chat.handle_close(self)
40         self.server.disconnect(self)
41
42 class ChatServer(dispatcher):
43     ‘‘‘
44     接收连接并且产生单个会话的类。他还会处理到其他会话的广播
45     ‘‘‘
46     def __init__(self, port, name):
47         #标准设置任务
48         dispatcher.__init__(self)
49         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
50         self.set_reuse_addr()
51         self.bind((‘‘, port))
52         self.listen(5)
53         self.name = name
54         self.sessions = []
55     def disconnect(self, session):
56         self.sessions.remove(session)
57
58     def broadcast(self, line):
59         for session in self.sessions:
60             session.push(line+‘\r\n‘)
61
62     def handle_accept(self):
63         conn, addr = self.accept()
64         self.sessions.append(ChatSessioin(self, conn))
65
66 if __name__ == ‘__main__‘:
67     s = ChatServer(PORT, NAME)
68     try: asyncore.loop()
69     except KeyboardInterrupt: print

运行这个程序后会发现,客户端虽然能够显示其它用户发送的信息,但不能识别是哪一个用户,而且整个程序没有登录登出等功能,下面我们就来扩展这些功能。

再次实现:

首先我们把服务器分为三个房间,登录房间,聊天室,登出房间,三个房间分别为三个类,这些类的父类拥有添加和删除会话 的功能。代码如下

 1 class Room(CommandHandler):
 2     ‘‘‘
 3     包括一个或多个用户(会话)的泛型环境,他负责基本的命令处理和广播
 4     ‘‘‘
 5
 6     def __init__(self, server):
 7         self.server = server
 8         self.sessions = []
 9
10     def add(self, session):
11         ‘一个会话用户已进入房间‘
12         self.sessions.append(session)
13
14     def remove(self, session):
15         ‘一个会话用户已离开房间‘
16         self.sessions.remove(session)
17
18     def broadcast(self, line):
19         ‘向房间中的所有会话发送一行‘
20         for session in self.sessions:
21             session.push(line)
22
23     def do_logout(self, session, line):
24         ‘响应logout命令‘
25         raise EndSession

登录房间继承room父类

 1 class LoginRoom(Room):
 2     ‘‘‘
 3     为刚刚连接上的用户准备的房间
 4     ‘‘‘
 5     def add(self, session):
 6         Room.add(self, session)
 7         #当用户进入时,问候他
 8         self.broadcast(‘Welcome to %s \r\n‘ % self.server.name)
 9
10     def unknown(self, session, cmd):
11         #所有未知命令(除了login或者logout除外)
12         #会导致一个警告
13         session.push(‘Please log in \nUse "login <nick>"\r\n‘)
14
15     def do_login(self, session, line):
16         name = line.strip()
17         #确保用户输入了名字
18         if not  name:
19             session.push(‘Please enter a name\r\n‘)
20         #确保用户名没有被使用
21         elif name in self.server.users:
22             session.push(‘The name "%s" is taken.\r\n‘ % name)
23             session.push(‘Please try again.\r\n‘)
24         else:
25             #名字没问题,所以存储在会话中
26             #将用户移动到主聊天室
27             session.name = name
28             session.enter(self.server.main_room)

  登录房间是让用户登录时所在的房间,在该房间内接收用户的登录命令,登陆成功后进入聊天房间。同样的,也有登出房间登出房间同理。

  聊天室房间负责处理say,look命令,say命令可以让用户在该房间内发言,并显示在其他的客户端上;look命令可以让用户查看当前聊天室所存在的用户。

 1 class ChatRoom(Room):
 2     ‘‘‘
 3     为多用户相互聊天准备房间
 4     ‘‘‘
 5     def add(self, session):
 6         #告诉所有人有新用户进入:
 7         self.broadcast(session.name + ‘ has entered the room\r\n‘)
 8         self.server.users[session.name] = session
 9         Room.add(self, session)
10
11     def remove(self, session):
12         Room.remove(self, session)
13         #告诉所有人有用户离开
14         self.broadcast(session.name + ‘ has left the room.\r\n‘)
15
16     def do_say(self, session, line):
17         self.broadcast(session.name +‘:‘ + line + ‘\r\n‘)
18
19     def do_look(self, session, line):
20         ‘处理look命令,该命令用于查看谁在房间‘
21         session.push(‘The following are in this room:\r\n‘)
22         for other in self.sessions:
23             session.push(other.name + ‘\r\n‘)

整个服务器程序的结构如下图:

时间: 2024-10-13 07:34:18

python实现虚拟茶话会的相关文章

创建 Python Virtualenv 虚拟隔离环境

video:创建 Python Virtualenv 虚拟隔离环境 python 虚拟环境 venv 简单用法 - littlemore - 博客园 创建 Python Virtualenv 虚拟隔离环境 注:早期的版本需要使用工具:pipenv.conda.virtualenv,至3.4版本之后就已经集成了该模块python -m venv python 的venv使用注意事项 在windows平台下的情况: python的venv环境不能完全脱离python环境运行,就是你把整个项目拷贝到一

python基础教程总结15——5 虚拟茶话会

聊天服务器: 服务器能接受来自不同用户的多个连接: 允许用户同时(并行)操作: 能解释命令,例如,say或者logout: 容易拓展 1. 初次实现 1.1 CharServer类 有问题................ #可接受连接的服务器 from asyncore import dispatcher import asyncore,socket class ChatServer(dispatcher): def handle_accept(self): conn.addr=self.acc

faker之python构造虚拟数据

python中可以使用faker来制造一些虚拟数据 首选安装faker pip install Faker 老版的叫法是faker-factory,但是已不适用 使用faker.Factory.create()来创建并初始化faker生成器(generator) 使用方法如下: from faker import Factory fake = Factory.create()   # OR from faker import Faker fake = Faker()   fake.name()

Python之虚拟环境管理

Python本身有很多个版本,第三方的Python包又有很多可用的版本,所以经常会遇到下面的问题: 运行不同的Python程序,需要使用不同版本的Python(2.x或3.x). 在同一中Python版本中,可能需要用到不同版本的第三方包,例如:Django 1.6或者Django 1.7 对于上面的问题,已经有很多现成的个工具可以解决.根据解决上面问题的方法,这些工具大概可以分为两类: Python 版本环境切换工具 特定Python版本虚拟环境切换工具 现有工具及介绍 下面看看现在流行的虚拟

[译]Python编写虚拟解释器

使用Python编写虚拟机解释器 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou,密码shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到程序: 1. LX终端(LXTerminal):Linux命令行终端,打开后会进入Bash环境,可以使用Linux命令2. GVim:非常好用的编辑器,最简单的用法可以参考课程Vim编辑器 3. 环境使用 使用R语言交互式环境输入实验所需的代码及文件,使用LX终端(LXTermina

python的虚拟运行环境

Python 虚拟环境:Virtualenv 博客分类: Python python 在进行python开发的时候避免不同版本python或python不同版本组件之间的冲突, 有必要配置python的虚拟环境,本博客转自http://liuzhijun.iteye.com/blog/1872241 virtualenv virtualenv用于创建独立的Python环境,多个Python相互独立,互不影响,它能够:1. 在没有权限的情况下安装新套件2. 不同应用可以使用不同的套件版本3. 套件

用virtualenv建立多个Python独立虚拟开发环境

1.安装virtualenv: pip install virtualenv 2.创建一个python的虚拟环境: virtualenv test_demo 用virtualenv创建虚拟环境,是通过复制全局的python解释器,达到环境的互不影响:新建的虚拟环境会自动复制python解释器环境保存到当前路径之下: 3.virtualenv虚拟环境: activate #进入虚拟环境 进入虚拟环境: deactivate #退出虚拟环境 4.指定python版本: virtualenv可以实现两

tox python项目虚拟环境管理自动化测试&amp;&amp;构建工具

tox 是一个方便的工具,可以帮助我们管理python 的虚拟环境,同时可以进行项目自动测试以及构建 tox 如何工作的 说明 从上图我们也可以看出如何在我们项目中使用tox 参考资料 https://github.com/tox-dev/tox https://tox.readthedocs.io/en/latest/ 原文地址:https://www.cnblogs.com/rongfengliang/p/10983048.html

python配置虚拟开发环境

问题 有的时候开发不同的业务,所需要的环境不一样.一直在同一个环境中开发时候,不同的包版本升级可能会导致另外的业务不能正常工作.另外,有的github上的项目需要的开发环境与你使用的环境不同,冒然的按照它的requirements安装相应的包会产生类似的问题.一般而言,针对这种情况,对不同的业务,如果是存在依赖包存在版本升降级问题,常规的办法是对不同的业务创建不同的虚拟环境,在各个业务下,先进入虚拟环境,然后需要那种依赖包再进行安装,这样就不会产生版本不一样,或者版本升级导致的其它业务不能正常工