Discuss / Python / 简易聊天室模块

简易聊天室模块

Topic source

苏生不语_

#1 Created at ... [Delete] [Delete and Lock User]
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/12/6 14:10
# @Author : Mr.Zuo
# @File : chatrom.py
# @desc : 简易聊天室
import socket
import threading
import logging

# 客户端 数据分隔符
CLIENT_SPLIT = ']]][[['
# 消息编码
MESSAGE_ENCODING = 'utf-8'
# TCP最大等待连接数
TCP_MAX_WAITING = 10
# 一次读取字节数
BUFFER_SIZE = 1024
# 默认主机名和端口
DEFAULT_ADDRESS = ('127.0.0.1', 8080)
logging.basicConfig(level=logging.INFO)


# 聊天室服务器
class Server(socket.socket):

    def __init__(self, address=DEFAULT_ADDRESS):
        super(Server, self).__init__(type=socket.SOCK_DGRAM)
        # 服务器地址
        self.__address = address
        # 保存客户端信息 key为用户名 value为用户地址
        self.__clients = dict()

    # 启动服务器
    def start(self):
        # 绑定UDP地址
        self.bind(self.__address)
        logging.info('【服务器已启动,主机:%s,端口:%s】' % self.__address)
        while True:
            try:
                # 接收用户消息
                data, addr = self.recvfrom(BUFFER_SIZE)
                data = data.decode(MESSAGE_ENCODING)
                # 如果data不包含分隔符,则是第一次发送
                if CLIENT_SPLIT not in data:
                    # 将该用户存入客户端字典
                    self.__clients[data] = addr
                    self.sys_message('欢迎%s进入聊天室' % data)
                else:
                    # 向聊天室广播
                    self.user_message(data, addr)
            except ConnectionError as e:
                logging.debug(e)

    # 像聊天室所有用户发送信息(除发送消息的用户)
    def user_message(self, msg, from_address=None):
        logging.info('接收到消息:%s' % msg)
        logging.info('当前客户端:%s' % self.__clients)
        for name, address in self.__clients.items():
            # 排除发送消息的客户端
            if from_address != address:
                self.sendto(msg.encode(MESSAGE_ENCODING), address)

    # 发送系统消息
    def sys_message(self, msg):
        msg = 'sys' + CLIENT_SPLIT + msg
        for name, address in self.__clients.items():
            self.sendto(msg.encode(MESSAGE_ENCODING), address)


# 聊天室客户端
class Client(socket.socket):

    def __init__(self, name, address=DEFAULT_ADDRESS):
        super(Client, self).__init__(type=socket.SOCK_DGRAM)
        # 服务器地址
        self.__address = address
        # 聊天室昵称
        self.__name = name

    # 启动客户端
    def start(self):
        logging.info('【客户端已启动】')
        # 启动后向服务器发送昵称和客户端地址
        self.sendto(self.__name.encode(MESSAGE_ENCODING), self.__address)
        # 启动子线程接收服务器消息
        t = threading.Thread(target=self.recv_handler)
        t.start()
        while True:
            msg = input()
            self.send_msg(msg)

    # 发送消息
    def send_msg(self, msg):
        # 将用户昵称加入消息
        data = (self.__name+CLIENT_SPLIT+msg).encode(MESSAGE_ENCODING)
        # 发送消息至服务器
        self.sendto(data, self.__address)
        self.show_msg(data)

    # 打印消息
    def show_msg(self, data):
        name, msg = data.decode(MESSAGE_ENCODING).split(CLIENT_SPLIT)
        if name == 'sys':
            print('----------%s----------' % msg)
        elif name == self.__name:
            print('%s:%s' % (name, msg))
        else:
            print('\t\t\t\t\t\t%s:%s' % (msg, name))

    # 接收服务器发送的数据
    def recv_handler(self):
        while True:
            data = self.recv(BUFFER_SIZE)
            self.show_msg(data)



# 创建服务器
from chatrom import Server

server = Server(address=('127.0.0.1', 8080))

server.start()

# 创建客户端
from chatrom import Server
c = Client('Alex1', address=('127.0.0.1', 8080))

c.start()

大勺子okc

#2 Created at ... [Delete] [Delete and Lock User]

客户端的handler函数里只有在客户端的一个显示功能,应该加上一个发送数据到服务器的功能,这样你输入的信息才能通过服务器在别人的客户端上显示,不然就是输入的东西只能在自己的界面看到,服务器并没有起到作用


  • 1

Reply