Python使用进程、线程来设计简单聊天室

聊天室服务器
思想步骤:

  1. 建立 Server Socket 对象,等待客户端连接
  2. 接收客户端连接,并保存到连接池
  3. 建立客户端线程,等待接受消息
  4. 接收到消息后,转发给其他所有客户端
  5. 收到 ‘exit’ 数据后,关闭客户端连接,将连接对象从连接池删除
import socket
import threading


class ClientThread(threading.Thread):
    def __init__(self, sock, addr, conn_pool, pool_lock):
        super().__init__()
        self.daemon = True
        self.sock = sock
        self.addr = addr
        self.conn_pool = conn_pool
        self.pool_lock = pool_lock

    def broadcast(self, msg):
        '''广播'''
        for addr, sock in self.conn_pool.items():
            if addr != self.addr:  # 排除自己
                sock.send(msg)  # 给其他人发消息

    def exit(self):
        '''退出'''
        self.sock.close()
        with self.pool_lock:
            self.conn_pool.pop(self.addr)

    def run(self):
        '''线程的主函数'''
        while True:
            msg = self.sock.recv(1024)
            if msg in [b'exit', b'']:
                self.exit()
                break
            else:
                self.broadcast(msg)


def main():
    '''主程序'''
    addr = ('0.0.0.0', 8000)  # 服务器地址
    sock = socket.socket()
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(addr)
    sock.listen(1024)
    print('服务器开始监听: %s:%s' % addr)

    # 连接池对象
    conn_pool = {}
    pool_lock = threading.Lock()

    while True:
        cli_sock, cli_addr = sock.accept()
        print('收到客户端连接: %s:%s' % cli_addr)
        with pool_lock:
            conn_pool[cli_addr] = cli_sock  # 将 cli_sock 放入连接池
        cli_thread = ClientThread(cli_sock, cli_addr, conn_pool, pool_lock)
        cli_thread.start()


if __name__ == "__main__":
    main()

聊天室客户端
思想步骤:

  1. 建立与服务器的连接
  2. 建立接收线程:收到消息后自动打印
  3. 建立发送线程:等待用户数据, 用户输入完后,将消息发送到服务器
  4. 用户输入 ‘exit’ 后,将消息发到服务器,然后关闭连接,最后退出客户端
import sys
import socket
import threading

class RecvThread(threading.Thread):
    '''消息接收线程'''

    def __init__(self, sock):
        super().__init__()
        self.daemon = True
        self.sock = sock

    def run(self):
        while True:
            msg = self.sock.recv(1024)
            print(msg.decode('utf-8'))

def main(host, port):
    addr = (host, port)
    sock = socket.socket()
    sock.connect(addr)  # 与服务器建立连接

    # 创建并启动消息接收线程
    recv_thread = RecvThread(sock)
    recv_thread.start()

    # 等待用户输入消息,并发送
    while True:
        msg = input('请输入: ')
        msg = msg.encode('utf-8')
        sock.send(msg)

        if msg == b'exit':
            sock.close()
            break

if __name__ == "__main__":
    try:
        host = sys.argv[1]
        port = int(sys.argv[2])
    except (IndexError, TypeError):
        print('请输入正确的参数')

    main(host, port)

运行结果:
在local(2)中输入qwer,local(3)中能接受到,服务器发生改变。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值