zoukankan      html  css  js  c++  java
  • 第24章 项目5:虚拟茶话会

    wxPython

    编写客户端需要用到wxPython,它是一个GUI工具包,

    下载地址:https://www.wxpython.org/download.php

    运行安装即可。

    当使用命令:import wx时,未报错,安装成功。

    聊天室客户端代码不能在 windows 下运行,因为代码使用 select 同时监听 socket 和输入流,在 Windows select 函数是由 WinSock 库提供,不能处理不是由 WinSock 定义的文件描述符。

    客户端代码还有个缺陷是,当某个客户端在输入消息但还未发送出去时,服务器也发送消息过来,这样会冲刷掉客户端正在输入的消息。这目前来看没办法解决的,唯一的解决方法是使用像 ncurses 终端库使用户输入和输出独立开,或者写一个GUI的程序。

    http://www.cnblogs.com/hazir/p/python_chat_room.html

    24-1.py 迷你服务器程序    

    from asyncore import dispatcher
    import asyncore

    class ChatServer(dispatcher): pass

    s = ChatServer()
    asyncore.loop()

    运行之后什么都没发生。

     

    24-2.py 可以接收连接的服务器

    # coding=utf-8
    from asyncore import dispatcher
    import socket, asyncore

    class ChatServer(dispatcher):

    def handle_accept(self):# 调用允许客户端连接的self.accpet函数,并返回一个连接和一个地址
    conn, addr = self.accept()
    print 'Connection attempt from', addr[0] # addr[0]是客户端的IP地址

    s = ChatServer()
    s.create_socket(socket.AF_INET, socket.SOCK_STREAM) # 服务器初始化,使用两个参数指定所需套接字的类型
    s.bind(('', 5005)) # 把服务器绑定到具体的地址上,,主机名为空(即本地主机),端口号为5005
    s.listen(5) # 调用服务器以告诉服务器要监听连接,并指定5个连接的代办事务
    asyncore.loop() # 启动服务器,循环监听

    客户端测试:telnet命令——通过如下步骤设置:

    1. 打开控制面板

    2. 程序和功能

    3. 打开或关闭WINDOWS功能

    4. CHECK TELNET 客户端。

    5. TELNET输入如果出现乱码:按下 CTRL+] 即可正常输入

    以上配置完毕后,运行24-2.py,并在cmd窗口输入测试命令:

    telnet 127.0.0.1 5005或者telnet localhost 5005

    客户端立即被断开,即cmd恢复到初始状态

    然后服务端出现如下:Connection attempt from 127.0.0.1

    24-3.py具有一些清理功能的基本服务器

    from asyncore import dispatcher
    import socket, asyncore

    PROT = 5005

    class ChatServer(dispatcher):

    def __init__(self, port):
    dispatcher.__init__(self)
    self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
    self.set_reuse_addr()
    self.bind(('',port))
    self.listen(5)

    def handle_accept(self):
    conn, addr = self.accept()
    print 'Connection attempt from', addr[0]

    if __name__ == '__main__':
    s = ChatServer(PROT)
    try: asyncore.loop()
    except KeyboardInterrupt: pass
    运行
    24-3.py,并在cmd窗口输入测试命令:telnet localhost 5005

    服务端出现如下:Connection attempt from 127.0.0.1

     

    ChatSession

    基本的ChatSession类用处不大,应在代码实现中为每个连接创建一个dispatcher对象。主要任务是收集来自客户端的数据进行响应,可以使用asynchat模块。

    为了让asynchat起作用,只要覆盖两个方法即可。

    (1) collect_incoming_data:在从套接字中读取一些bit文本时调用。

    (2) found_terminator:在读取一个结束符时调用。结束符通过set_terminiator方法设置,一般设置为" ".

    24-4.py 带有ChatSession类的服务器程序

    # coding=utf-8
    from asyncore import dispatcher
    from asynchat import async_chat
    import socket, asyncore

    PORT = 5005

    class ChatSession(async_chat):
    """
    负责和单用户通信
    """

    def __init__(self, sock):
    async_chat.__init__(self, sock)
    self.set_terminator(" ")
    self.data = []

    def collect_incoming_data(self, data):
    self.data.append(data)

    def found_terminator(self):
    line = ''.join(self.data)
    self.data = []
    # 处理这行数据.....
    print line

    class ChatServer(dispatcher):

    def __init__(self, port):
    dispatcher.__init__(self)
    self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
    self.set_reuse_addr()
    self.bind(('',port))
    self.listen(5)
    self.sessions = []

    def handle_accept(self):
    conn, addr = self.accept()
    self.sessions.append(ChatSession(conn))

    if __name__ == '__main__':
    s = ChatServer(PORT)
    try: asyncore.loop()
    except KeyboardInterrupt: print

    运行24-4.py,并在cmd窗口输入测试命令:telnet localhost 5005

    运行之后出现客户端界面,而连接没有马上断掉

    输入1111并回车,在该界面无任何输出,而服务端输出如下:

    输入Hello, world!并回车:

    实现了同时使用两个或者更多客户端进行连接,在客户端输入的每一行都会在服务器终端打印出来。

    整合

    还需要将用户的发言广播给其他的用户,可以通过在服务器端遍历回话的列表,将发言行写到每一个客户端里面。此外,必须保证在客户单断开连接后,将它从会话列表中移除。通过重写事件处理方法handle_close 来实现这个功能。

    24-5 simple_chat.py ——简单的聊天服务器
    # coding=utf-8
    from asyncore import dispatcher
    from asynchat import async_chat
    import socket, asyncore

    PORT = 5005
    NAME= 'TestChat'

    class
    ChatSession(async_chat):
    """
    处理服务器和一个用户之间连接的类
    """
    def __init__(self, server, sock):
    # 标准设置任务:
    async_chat.__init__(self, sock)
    self.server = server
    self.set_terminator(" ")
    self.data = []
    # 问候用户:
    self.push('Welcome to %s ' % self.server.name)

    def collect_incoming_data(self, data):
    self.data.append(data)

    def found_terminator(self):
    """
    如果发现了一个终止对象,也就意味着读入了一个完整的行,将其广播给每个人。
    """
    line = ''.join(self.data)
    self.data = []
    self.server.broadcast(line)

    def handle_close(self):
    async_chat.handle_close(self)
    self.server.disconnect(self)

    class ChatServer(dispatcher):
    """
    接受连接并且产生单个会话的类。它还会处理到其他会话的广播。
    """
    def __init__(self, port, name):
    # Standrad setup tasks
    dispatcher.__init__(self)
    self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
    self.set_reuse_addr()
    self.bind(('',port))
    self.listen(5)
    self.name = name
    self.sessions = []

    def disconnect(self, session):
    self.sessions.remove(session)

    def broadcast(self, line):
    for session in self.sessions:
    session.push(line+ ' ')

    def handle_accept(self):
    conn, addr = self.accept()
    self.sessions.append(ChatSession(self, conn))

    if __name__ == '__main__':
    s = ChatServer(PORT, NAME)
    try: asyncore.loop()
    except KeyboardInterrupt: print

    运行simple_chat.py,并在cmd窗口输入测试命令:telnet localhost 5005

    运行之后出现客户端界面:

    输入Hello, world!并回车,客户端输出该字符串:

    而服务端无输出。

    聊天服务器的最终版本

    24-6 稍复杂的聊天服务器 chatserver.py

    运行chatserver.py之后,打开两个cmd窗口,均输入测试命令:telnet localhost 5005,回车。

    login命令:第一个窗口输入login maguns,第二个输入login dilbert

    look命令:

    say 命令:

    重复登陆:

    退出:

  • 相关阅读:
    简明python教程九----异常
    简明python教程八----输入/输出
    简明python教程七----面向对象的编程(下)
    vue --- 生命周期
    es6 ----- export 和 import
    jq ---- 实现浏览器全屏
    Vue项目自动转换 px 为 rem,高保真还原设计图
    vue ---- 实现手机端(左滑 删除。右划 正常)
    js---- localStorage的基本用法
    点击 下载文件保存
  • 原文地址:https://www.cnblogs.com/Sumomo0516/p/6131704.html
Copyright © 2011-2022 走看看