博客
关于我
使用 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 字段合并问题(group_concat)
    查看>>
    mysql 字段类型类型
    查看>>
    MySQL 字符串截取函数,字段截取,字符串截取
    查看>>
    MySQL 存储引擎
    查看>>
    mysql 存储过程 注入_mysql 视图 事务 存储过程 SQL注入
    查看>>
    MySQL 存储过程参数:in、out、inout
    查看>>
    mysql 存储过程每隔一段时间执行一次
    查看>>
    mysql 存在update不存在insert
    查看>>
    Mysql 学习总结(86)—— Mysql 的 JSON 数据类型正确使用姿势
    查看>>
    Mysql 学习总结(87)—— Mysql 执行计划(Explain)再总结
    查看>>
    Mysql 学习总结(88)—— Mysql 官方为什么不推荐用雪花 id 和 uuid 做 MySQL 主键
    查看>>
    Mysql 学习总结(89)—— Mysql 库表容量统计
    查看>>
    mysql 实现主从复制/主从同步
    查看>>
    mysql 审核_审核MySQL数据库上的登录
    查看>>
    mysql 导入 sql 文件时 ERROR 1046 (3D000) no database selected 错误的解决
    查看>>
    mysql 导入导出大文件
    查看>>
    MySQL 导出数据
    查看>>
    mysql 将null转代为0
    查看>>
    mysql 常用
    查看>>
    MySQL 常用列类型
    查看>>