博客
关于我
使用 Python 编写一个聊天小程序
阅读量:465 次
发布时间:2019-03-06

本文共 5703 字,大约阅读时间需要 19 分钟。

用Python轻松构建聊天应用:从零到成型

聊天应用程序是许多开发者入门的经典项目之一。通过合理利用多线程和网络编程,我们可以在短短几百行代码中完成一个功能齐全的聊天系统。以下将详细介绍如何从零开始,逐步搭建一个无依赖的聊天应用程序。

服务器端:多线程处理聊天

服务器端的主要功能包括接收客户端连接、处理消息广播以及管理客户端会话。我们使用标准的socket库和多线程技术来实现这一点。

  • 导入必要的库
  • from socket import AF_INET, socket, SOCK_STREAM
    from threading import Thread
    1. 初始化常量
    2. BUFSIZ = 1024  # 数据传输缓冲大小
      ADDR = (HOST, PORT) # 服务器地址和端口
      1. 接收连接并处理消息
      2. def accept_incoming_connections():
        while True:
        client, client_address = SERVER.accept()
        print(f"{client_address} has connected.")
        client.send("欢迎来到聊天室!请输入你的名字并按回车。".encode("utf-8"))
        addresses[client] = client_address
        Thread(target=handle_client, args=(client,)).start()
        1. 处理单个客户端连接
        2. def handle_client(client):
          name = client.recv(BUFSIZ).decode("utf-8")
          welcome = f"欢迎 {name}!输入 {quit} 退出。"
          client.send(welcome.encode("utf-8"))
          broadcast(f"{name} 已加入聊天。", name)
          clients[client] = name
          while True:
          msg = client.recv(BUFSIZ)
          if not msg:
          break
          if msg.decode("utf-8") == "{quit}":
          client.send("{quit}".encode("utf-8"))
          client.close()
          del clients[client]
          broadcast(f"{name} 已离开聊天。", name)
          break
          broadcast(f"{name}: {msg.decode('utf-8')}", name)
          1. 广播消息
          2. def broadcast(msg, prefix=""):
            for sock in clients:
            sock.send(f"{prefix}{msg}".encode("utf-8"))
            1. 启动服务器
            2. if __name__ == "__main__":
              SERVER.listen(5)
              print("正在侦听连接...")
              accept_thread = Thread(target=accept_incoming_connections)
              accept_thread.start()
              accept_thread.join()
              SERVER.close()

              客户端端:GUI聊天界面

              客户端使用Tkinter库创建GUI界面,支持消息发送和接收。

            3. 导入必要的库
            4. from socket import AF_INET, socket, SOCK_STREAM
              from threading import Thread
              import tkinter
              1. 初始化GUI元素
              2. top = tkinter.Tk()
                top.title("聊天室")
                messages_frame = tkinter.Frame(top)
                my_msg = tkinter.StringVar()
                my_msg.set("输入你的消息。")
                1. 消息列表和滚动条
                2. msg_list = tkinter.Listbox(messages_frame, height=15, width=50, yscrollcommand=scrollbar.set)
                  scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
                  msg_list.pack(side=tkinter.LEFT, fill=tkinter.BOTH)
                  msg_list.pack()
                  messages_frame.pack()
                  1. 消息输入和发送功能
                  2. entry_field = tkinter.Entry(top, textvariable=my_msg)
                    entry_field.bind("
                    ", send)
                    entry_field.pack()
                    send_button = tkinter.Button(top, text="发送", command=send)
                    send_button.pack()
                    1. 连接到服务器并启动接收消息线程
                    2. HOST = input("请输入服务器地址:")
                      PORT = input("请输入服务器端口:")
                      if not PORT:
                      PORT = 33000
                      ADDR = (HOST, PORT)
                      client_socket = socket(AF_INET, SOCK_STREAM)
                      client_socket.connect(ADDR)
                      receive_thread = Thread(target=receive)
                      receive_thread.start()
                      tkinter.mainloop()

                      完整代码结构

                      • 服务器脚本
                      #!/usr/bin/env python3
                      from socket import AF_INET, socket, SOCK_STREAM
                      from threading import Thread
                      BUFSIZ = 1024
                      ADDR = (input("请输入服务器地址:"), int(input("请输入服务器端口:") or 33000))
                      SERVER = socket(AF_INET, SOCK_STREAM)
                      SERVER.bind(ADDR)
                      def accept_incoming_connections():
                      while True:
                      client, client_address = SERVER.accept()
                      print(f"{client_address} 已连接。")
                      client.send("欢迎来到聊天室!请输入你的名字并按回车。".encode("utf-8"))
                      addresses[client] = client_address
                      Thread(target=handle_client, args=(client,)).start()
                      def handle_client(client):
                      name = client.recv(BUFSIZ).decode("utf-8")
                      welcome = f"欢迎 {name}!输入 {quit} 退出。"
                      client.send(welcome.encode("utf-8"))
                      broadcast(f"{name} 已加入聊天。", name)
                      clients[client] = name
                      while True:
                      msg = client.recv(BUFSIZ)
                      if not msg:
                      break
                      if msg.decode("utf-8") == "{quit}":
                      client.send("{quit}".encode("utf-8"))
                      client.close()
                      del clients[client]
                      broadcast(f"{name} 已离开聊天。", name)
                      break
                      broadcast(f"{name}: {msg.decode('utf-8')}", name)
                      def broadcast(msg, prefix=""):
                      for sock in clients:
                      sock.send(f"{prefix}{msg}".encode("utf-8"))
                      if __name__ == "__main__":
                      SERVER.listen(5)
                      print("正在侦听连接...")
                      accept_thread = Thread(target=accept_incoming_connections)
                      accept_thread.start()
                      accept_thread.join()
                      SERVER.close()
                      • 客户端脚本
                      #!/usr/bin/env python3
                      from socket import AF_INET, socket, SOCK_STREAM
                      from threading import Thread
                      import tkinter
                      top = tkinter.Tk()
                      top.title("聊天室")
                      messages_frame = tkinter.Frame(top)
                      my_msg = tkinter.StringVar()
                      my_msg.set("输入你的消息。")
                      scrollbar = tkinter.Scrollbar(messages_frame)
                      msg_list = tkinter.Listbox(messages_frame, height=15, width=50, yscrollcommand=scrollbar.set)
                      scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
                      msg_list.pack(side=tkinter.LEFT, fill=tkinter.BOTH)
                      msg_list.pack()
                      messages_frame.pack()
                      entry_field = tkinter.Entry(top, textvariable=my_msg)
                      entry_field.bind("
                      ", send)
                      entry_field.pack()
                      send_button = tkinter.Button(top, text="发送", command=send)
                      send_button.pack()
                      top.protocol("WM_DELETE_WINDOW", on_closing)
                      def send(event=None):
                      msg = my_msg.get()
                      my_msg.set("")
                      if msg.strip() == "{quit}":
                      client_socket.close()
                      top.quit()
                      else:
                      client_socket.send(msg.encode("utf-8"))
                      if msg:
                      broadcast(msg, my_msg.get())
                      def on_closing(event=None):
                      my_msg.set("{quit}")
                      send()
                      HOST = input("请输入服务器地址:")
                      PORT = int(input("请输入服务器端口:") or 33000)
                      ADDR = (HOST, PORT)
                      client_socket = socket(AF_INET, SOCK_STREAM)
                      client_socket.connect(ADDR)
                      def receive():
                      while True:
                      try:
                      msg = client_socket.recv(BUFSIZ).decode("utf-8")
                      msg_list.insert(tkinter.END, msg)
                      except OSError:
                      break
                      receive_thread = Thread(target=receive)
                      receive_thread.start()
                      tkinter.mainloop()

                      通过以上代码,我们可以轻松搭建一个功能齐全的聊天应用程序。服务器端支持多人在线聊天,客户端提供友好的GUI界面。整个系统不依赖任何第三方库,完全由标准Python库驱动,实现了高效的消息传输和多线程处理。

    转载地址:http://vhybz.baihongyu.com/

    你可能感兴趣的文章
    MySql 查询以逗号分隔的字符串的方法(正则)
    查看>>
    MySQL 查询优化:提速查询效率的13大秘籍(避免使用SELECT 、分页查询的优化、合理使用连接、子查询的优化)(上)
    查看>>
    mysql 查询数据库所有表的字段信息
    查看>>
    【Java基础】什么是面向对象?
    查看>>
    mysql 查询,正数降序排序,负数升序排序
    查看>>
    MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)...
    查看>>
    mysql 死锁 Deadlock found when trying to get lock; try restarting transaction
    查看>>
    mysql 死锁(先delete 后insert)日志分析
    查看>>
    MySQL 死锁了,怎么办?
    查看>>
    MySQL 深度分页性能急剧下降,该如何优化?
    查看>>
    MySQL 深度分页性能急剧下降,该如何优化?
    查看>>
    MySQL 添加列,修改列,删除列
    查看>>
    mysql 添加索引
    查看>>
    MySQL 添加索引,删除索引及其用法
    查看>>
    mysql 状态检查,备份,修复
    查看>>
    MySQL 用 limit 为什么会影响性能?
    查看>>
    MySQL 用 limit 为什么会影响性能?有什么优化方案?
    查看>>
    MySQL 用户权限管理:授权、撤销、密码更新和用户删除(图文解析)
    查看>>
    mysql 用户管理和权限设置
    查看>>
    MySQL 的 varchar 水真的太深了!
    查看>>