python最强大的是什么?库支持!!有了强大的库支持,一个简单的聊天软件实现就更简单了,本项目思路如下

  1. # 项目思路
  2. 1. 服务器的工作
  3. * 初始化服务器
  4. * 新建一个聊天房间
  5. * 维护一个已链接用户的会话列表
  6. * 维护一个已登录用户的字典,用户名和会话
  7. * 监听端口,接受会话,并启动一个ChatSession处理
  8.  
  9. 2. 会话线程
  10. * 初始化一个接收数据缓冲区
  11. * 处理用户输入的命令,并提醒用户先登录(也就是说目前指处理登陆命令)
  12. * 将用户输入的数据加入缓冲区
  13. * 用户一次输入结束后,将缓冲区数据发送,并清空缓冲区
  14.  
  15. 3. 命令分发
  16. * 对用的输入进行分割,并将对应的命令分发到相应的处理函数,如果没有则采用默认处理函数
  17.  
  18. 4. 房间,继承自命令分发类,即:具有处理命令能力的房间
  19.  
  20. 5. LoginRoom,继承自Room,处理登陆相关的命令
  21. * 加入房间,有用户进入房间,欢迎该用户
  22. * 登录命令,登陆成功之后进入房间,将该session加入队列
  23.  
  24. 6. ChatRoom,继承自Room,处理发言、查看所有用户等命令
  25.  
  26. 7. LogoutRoom,继承自Room,处理用户登出,相当于用户输入登出命令之后进入一个房间,
  27. 然后抛出异常通知ChatSession关闭线程

代码如下:

  1. #! /usr/bin/env python
  2. # -*- coding=utf-8 -*-
  3.  
  4. from asyncore import dispatcher
  5. import socket
  6. import asyncore
  7. from asynchat import async_chat
  8.  
  9. # 服务器监听端口号
  10. PORT = 5005
  11. # 服务器名称
  12. NAME = 'QQ'
  13.  
  14. class EndException(Exception):
  15. pass
  16.  
  17. class CommandHandler:
  18. '''
  19. 用来处理用户输入简单的命令
  20. '''
  21.  
  22. def unknown(self, session, cmd):
  23. '''处理未知命令'''
  24. session.push('Unknown command %s\r\n' %cmd)
  25.  
  26. def handler(self, session, line):
  27. '''
  28. 处理命令(命令路由),根据用户输入分析储命令,调用对应的处理程序
  29. '''
  30. if not line.strip():
  31. # 如果输入为空,返回,不做处理
  32. return
  33. # 切分命令
  34. print line + '----------'
  35. parts = line.split(' ', 1)
  36. cmd = parts[0]
  37. try:
  38. line = parts[1]
  39. except IndexError:
  40. line = ''
  41. method = getattr(self, 'do_' + cmd, None)
  42. try:
  43. method(session, line)
  44. except TypeError:
  45. # 如果该方法不存在,说明不能处理该命令,未知命令
  46. self.unknown(session, cmd)
  47.  
  48. class Room(CommandHandler):
  49. '''
  50. 房间类,用来处理具体情况的命令
  51. '''
  52.  
  53. def __init__(self, server):
  54. '房间初始化的时候,需要一个服务器对象用来获得服务器信息,初始化房间内的人员'
  55.  
  56. self.server = server
  57. self.sessions = []
  58.  
  59. def add(self, session):
  60. '''
  61. 用户加入该房间
  62. '''
  63. self.sessions.append(session)
  64.  
  65. def remove(self, session):
  66. '用户退出房间'
  67. self.sessions.remove(session)
  68.  
  69. def broadcast(self, line):
  70. '用户在房间中发言'
  71. for session in self.sessions:
  72. session.push(line)
  73.  
  74. def do_logout(self, sessioni, line):
  75. '用户退出房间'
  76. raise EndException
  77.  
  78. class LoginRoom(Room):
  79. '''
  80. 用户登录房间,处理用户登录房间的一些操作
  81. '''
  82.  
  83. def add(self, session):
  84. '扩展父类方法,在加入房间之后,给用户发送欢迎语'
  85. Room.add(self, session)
  86. session.push('welcome to %s \r\n' % self.server.name)
  87.  
  88. def unknown(self, session, cmd):
  89. '处理未知命令,提示用户输入登录命令'
  90. session.push('please log in \r "Use login <nick>" \r\n')
  91.  
  92. def do_login(self, session, line):
  93. '处理用户登录命令'
  94. name = line.strip()
  95. if not name:
  96. # 如果没有输入名称,提示用户输入
  97. session.push('Please input a name')
  98. elif name in self.server.users:
  99. # 如果名称已被占用
  100. session.push('the % is taken \r\n' %name)
  101. session.push('Please try again')
  102. else:
  103. # 如果正常则让用户进入房间
  104. session.name = name
  105. session.enter(self.server.main_room)
  106.  
  107. class ChatRoom(Room):
  108. '''
  109. 聊天房间,处理用户在房间中聊天的命令
  110. '''
  111.  
  112. def add(self, session):
  113. '用户进入聊天房间的时候,通知其他用户'
  114. Room.add(self, session)
  115. self.broadcast('%s has enter in the room \r\n' %session.name)
  116. self.server.users[session.name] = session
  117.  
  118. def remove(self, session):
  119. '提醒其他用户,xx离开房间'
  120. Room.remove(self, session)
  121. self.broadcast('%s has left the room \r\n' %session.name)
  122.  
  123. def do_say(self, session, line):
  124. '用户发言'
  125. self.broadcast(session.name + ':' + line + '\r\n')
  126.  
  127. def do_look(self, session, line):
  128. '查看房间中所有用户'
  129. self.broadcast('the following are in the room: \r\n')
  130. for user in self.sessions:
  131. self.broadcast(user.name + '\r\n')
  132.  
  133. class LogoutRoom(Room):
  134. '''
  135. 用户退出房间,所需要的命令
  136. '''
  137.  
  138. def do_logout(self, session, line):
  139. try:
  140. del self.server.users[session.name]
  141. except KeyError:
  142. pass
  143.  
  144. class ChatSession(async_chat):
  145. '''
  146. 具体处理客户端链接, 接受客户端发送来的信息,
  147. 广播给所有在线的客户端,关闭连接,
  148. 服务器保留所有连接到服务器的会话
  149. '''
  150.  
  151. def __init__(self, server, sock):
  152. ''
  153. async_chat.__init__(self, sock)
  154. self.server = server
  155. self.set_terminator('\r\n')
  156. self.data = []
  157. self.name = None
  158.  
  159. # 如果有新用户连接,则先要求登陆,登陆成功以后进入房间
  160. self.enter(LoginRoom(self.server))
  161.  
  162. def enter(self, room):
  163. try:
  164. cur = self.room
  165. except AttributeError:
  166. pass
  167. else:
  168. cur.remove(self)
  169. self.room = room
  170. room.add(self)
  171.  
  172. def collect_incoming_data(self, data):
  173. self.data.append(data)
  174.  
  175. def found_terminator(self):
  176. line = "".join(self.data)
  177. self.data = []
  178. try:
  179. self.room.handler(self, line)
  180. except EndException:
  181. self.handle_close()
  182.  
  183. def handle_close(self):
  184. async_chat.handle_close(self)
  185. self.enter(LogoutRoom(self))
  186.  
  187. class ChatServer(dispatcher):
  188. '''
  189. 服务器,负责接受客户端链接并分配给具体的程序(线程处理)
  190. '''
  191.  
  192. def __init__(self, port, name):
  193. '初始化服务器,初始会话列表,初始化用户字典(用户名对应用户session),初始化服务器主房间'
  194. dispatcher.__init__(self)
  195. self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  196. self.set_reuse_addr()
  197. self.bind(('', port))
  198. self.listen(5)
  199. self.sessions = []
  200. self.users = {}
  201. self.name = name
  202. self.main_room = ChatRoom(self)
  203.  
  204. def handle_accept(self):
  205. conn, addr = self.accept()
  206. print 'connection attemp from ', addr[0]
  207. ChatSession(self, conn)
  208.  
  209. s = ChatServer(PORT, NAME)
  210. try:
  211. asyncore.loop()
  212. except KeyboardInterrupt:
  213. pass

其实从第一个练习开始我就开始意识到,书中的引导是逐步的——使用的是迭代式的开发,一开始知识一个简单的例子视线了基本的功能,然后基于简单的列子将代码模块化,逐渐加功能,我也是试着这样做的,但是鉴于篇幅,其他代码就没有贴上来,在完整的代码可以下载

再进行本练习中,有一下基础知识得到巩固:

  1. # 判断正在运行的模块是直接运行还是被import执行的,即:
  2. # 直接运行的话__name='__main__'
  3. # 如果是import的话就不是__main__
  4. if __name__ == '__main__':
  5.  
  6. # 变量作用域
  7. data = 123
  8. * 在函数内部申明,作用域就是函数内部,
  9. * 在类内部申明就是类变量,访问的时候直接data
  10. * 在类内部的函数内部申明如:self.data=124,调用的时候只能是self.data,如果使用data,默认查找的是全局变量
  11. * 如果不适用self指明,python默认调用的全局变量
  12. * python变量可以重名,在同一作用于内如果已经定义过,只是进赋值
  13.  
  14. # 在子类方法内部调用父类方法(如:Room父类,ChatRoom子类)
  15. Room.__init__()

完整代码

http://pan.baidu.com/s/1nu5KE4T

python练习四—简单的聊天软件的更多相关文章

  1. 通过python 构建一个简单的聊天服务器

    构建一个 Python 聊天服务器 一个简单的聊天服务器 现在您已经了解了 Python 中基本的网络 API:接下来可以在一个简单的应用程序中应用这些知识了.在本节中,将构建一个简单的聊天服务器.使 ...

  2. 【Python网络编程】多线程聊天软件程序

    课程设计的时候制作的多线程聊天软件程序 基于python3.4.3 import socket import pickle import threading import tkinter import ...

  3. Netty学习笔记(四) 简单的聊天室功能之服务端开发

    前面三个章节,我们使用了Netty实现了DISCARD丢弃服务和回复以及自定义编码解码,这篇博客,我们要用Netty实现简单的聊天室功能. Ps: 突然想起来大学里面有个课程实训,给予UDP还是TCP ...

  4. python使用websocket简单组建聊天室

    server端 ###websocket_server### import socket import threading sock = socket.socket(socket.AF_INET, s ...

  5. 用python实现一个简单的聊天功能,tcp,udp,socketserver版本

    基于tcp协议版本 服务器端 import socket server = socket.socket() server.bind(('127.0.0.1', 8001)) server.listen ...

  6. Python Socket实现简单的聊天室

    通过参考其他牛人的文章和代码,  再根据自己的理解总结得出,  说明已经加在注释中, FYI 主要参考文章: http://blog.csdn.net/dk_zhe/article/details/3 ...

  7. 使用python编写的简单远程管理软件

    因为用户可以选择是否同意被控制,所以并不算是木马. 使用python3.7,spyder,在windows 10 开发. client为控制端,server为被控端. 参考 mygithub http ...

  8. python实现简单的聊天小程序

    概要 这是一个使用python实现一个简单的聊天室的功能,里面包含群聊,私聊两种聊天方式.实现的方式是使用套接字编程的一个使用TCP协议 c/s结构的聊天室 实现思路 x01 服务端的建立 首先,在服 ...

  9. Java实现 简单聊天软件

    简单的聊天软件 //客户端 package yjd9; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; ...

随机推荐

  1. 关于阿里云ECS服务器修改远程端口的一点总结

    般修改公司的远程服务器的登录端口号分为两大步: 一.修改注册表中的两个地方的端口号:(注册表打开命令:regedit) [HKEY_LOCAL_MACHINE\SYSTEM\CurrentContro ...

  2. 在IIS7上导出所有应用程序池的方法批量域名绑定

    在IIS7+上导出所有应用程序池的方法:%windir%/system32/inetsrv/appcmd list apppool /config /xml > c:/apppools.xml ...

  3. VMware虚拟机Linux增加磁盘空间的扩容操作

    转载自点击打开链接 用VMwareware虚拟机安装的Red Hat Enterprise Linux系统剩余空间不足,造成软件无法正常安装.如果重新装一遍系统就需要重新配置好开发环境和软件的安装配置 ...

  4. php面试题--并列排名问题

    给定一个二维数组: <?php $data = [ ['name' =>'j1', 'score' => '80'], ['name' =>'j2', 'score' => ...

  5. Thread,ThreadPool,Task

    线程分为前台和后台.比如我们直接new一个Thread这就是前台线程. 前台线程一定会执行. 比如我们创建2个线程:1号,2号,同时执行,假设1号是主线程,1执行完了,依旧会等待2执行完成,整个程序才 ...

  6. div+css+position实现简单的纵向导航栏

    完成效果: 这应该是很简单的纵向导航栏了. OK,进入正题 首先,我们看上面的效果图可以分析得出,要实现这个效果需要用到的技术点 1.hover 2.position 3.布局 我认为在这个效果的实现 ...

  7. IO在Socket中的应用

    一.BIO 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服务端进行通信,默认情况下服务端需要对每个连接 ...

  8. day_12函数默认值,数据类型的补充,函数对象名称空间与作用域,函数的嵌套定义

    复习, 昨天讲了字符串的比较,按照从左往右比较每一个字符,通过字符对应的ASCII码进行比较 函数的参数,‘ 实参与形参 形参:在函数定义时()中出现的参数 实参,在函数调用时()中出现的参数 实参的 ...

  9. VS2013和NuGet

    1.前言 有时候在使用VS2013时需要用到第三方的dll,这时候NuGet就是一个很方便的工具.但是这个小东东也是和VS不同的版本相关的,最开始不知道,乱安装一气,最后就是很多情况下不能用.这两天在 ...

  10. Windows 10 IoT Core 17133 for Insider 版本更新

    今天,微软发布了Windows 10 IoT Core 17133 for Insider 版本更新,本次更新只修正了一些Bug,没有发布新的特性.用户可以登录Windows Device Porta ...