Python 多人聊天工具 ( 多线程 )

程序实现:
1、单或多客户端使用 telnet 登陆服务端 ( 可远程 ) 进行会话
2、服务端实现登陆、注册、退出功能
3、客户端发送的消息会被广播到已经登陆的其他用户界面
4、连接到服务端后,可以执行相应的程序指令

程序代码:https://coding.net/u/wangxiaoqiangs/p/pycode/git/tree/master/socket/GServer

GServer.py

#!/usr/bin/env python
# coding: utf-8
# author: Xiao Guaishou

import socket
from db import DB
from threading import currentThread, Thread

class HandlerThread(object):
    queue = [] # sockect 队列
    db = DB()

    def __init__(self, sock):
        self.sock = sock

    def recv(self):
        data = self.sock.recv(1024).strip() # 如果使用 while 接收数据时,会导致用户必须多敲一次回车键
        return data

    def send(self, data):
        self.sock.sendall(‘\n[System]: %s\n‘ % data)

    # 向队列中广播消息
    def broadcast(self, user, data):
        for sock in self.queue:
            sock.sendall(‘\n[%s]: %s\n‘ % (user, data))

    # 关闭客户端连接
    def stop(self):
        self.send(‘ByeBye!‘)
        self.sock.close()
        self.queue.remove(self.sock) # 关闭连接后,记得从队列中删除

    # 程序入口
    def handler(self):
        funcdict = {
                    ‘login‘: self.login,
                    ‘register‘: self.register
        }

        try:
            thname = currentThread().getName()
            print(‘[%s] Got connection from %s‘ % (thname, self.sock.getpeername())) # 该程序中所有 print 的数据,将全部使用 loging 模块代替

            self.send(‘请选择功能:login/register/exit‘)

            data = self.recv()
            if data == ‘exit‘:
                self.stop() # 其实这里应该单独使用 self.sock.close() 来关闭连接,因为这时队列中并没有该连接,不过有了下面的捕获就没有问题了 ^_^
            elif data in funcdict:
                return funcdict.get(data)()
            else:
                self.handler()
        except: # 如果这里不捕获一下,就无法正常断开客户端连接
            pass

    # 处理用户登陆
    def login(self):
        self.send(‘Login... 请输入用户名密码,格式:User Password,输入 Server: 执行程序指令!‘)
        user_data = self.recv()

        # 程序内部指令
        if user_data == ‘Server:‘:
            self.send(‘\n\tServer:use reged\t切换到注册页\n\tServer:exit\t\t退出系统‘)
            user_data = self.recv()
            if user_data == ‘Server:use reged‘:
                self.register()
            elif user_data == ‘Server:exit‘:
                self.stop()
            else:
                self.send(‘输入错误...‘)

        datalist = user_data.split()

        # 判断用户输入,格式是否正确
        if len(datalist) == 2:
            user = datalist[0]
            password = datalist[1]

            db_data = self.db.get_data() or {}

            if user in db_data and password == db_data.get(user):
                self.queue.append(self.sock) # 有权限登陆系统者,连接被加入到队列中
                self.send(‘欢迎加入聊天室,输入 Server: 获取功能方法!‘)
                self.broadcast(‘System‘, ‘[%s] 加入聊天室!‘ % user)
                self.chat_room(user)
            else:
                self.send(‘用户名、密码错误!‘)
                self.login()
        self.login()

    def register(self):
        self.send(‘Register... 请输入用户名密码,格式:User Password,输入 Server: 执行程序指令!‘)
        user_data = self.recv()

        if user_data == ‘Server:‘:
            self.send(‘\n\tServer:use login\t切换到注册页\n\tServer:exit\t\t退出系统‘)
            user_data = self.recv()
            if user_data == ‘Server:login‘:
                self.login()
            elif user_data == ‘Server:exit‘:
                self.stop()
            else:
                self.send(‘输入错误...‘)

        datalist = user_data.split()

        if len(datalist) == 2:
            user = datalist[0]
            password = datalist[1]

            db_data = self.db.get_data() or {}

            if user in db_data:
                self.send(‘该用户名已被注册!‘)
                self.register()
            else:
                db_data[user] = password
                self.db.put_data(db_data)
                self.queue.append(self.sock)
                self.broadcast(‘System‘, ‘新用户 [%s] 加入聊天室!‘ % user)
                self.chat_room(user)
        self.register()

    def chat_room(self, user):
        user_data = self.recv()
        if user_data == ‘Server:‘:
            self.send(‘\n\tServer:logout\t退出聊天室‘)
            user_data = self.recv()
            if user_data == ‘Server:logout‘:
                self.stop()
                return # 这里如果不加 return ,会将客户端执行的 Server: 指令也广播出去
            else:
                self.send(‘输入错误...‘)
                self.chat_room(user)
        else:
            self.broadcast(user, user_data)
            self.chat_room(user)

# 为每连接创建线程
def Startthread(sock, addr):
    print(‘Received new client connection. %s:%s‘ % (addr[0], addr[1]))

    th = HandlerThread(sock)
    t = Thread(target=th.handler)
    t.setDaemon(True)
    t.start()

# 启动服务
def Server():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((‘0.0.0.0‘, 17170))
    s.listen(1)

    while True:
        try:
            sock, addr = s.accept()
        except KeyboardInterrupt:
            exit(‘\nByeBye!‘)

        Startthread(sock, addr)

    s.close()

if __name__ == ‘__main__‘:
    Server()

db.py

# coding: utf-8

import json

# 创建一个类,代替数据库
class DB(object):
    def __init__(self, path=‘Storage.db‘):
        self.path = path

    def get_data(self, data=None):
        try:
            with open(self.path) as f:
                data = json.load(f)
        except IOError as e:
            return data # 首次取数据时,由于文件不存在或没数据,将返回默认值 None
        finally:
            return data

    def put_data(self, data):
        with open(self.path, ‘w‘) as f:
            json.dump(data, f)
时间: 2024-07-30 00:13:46

Python 多人聊天工具 ( 多线程 )的相关文章

Java NIO实现的C/S模式多人聊天工具

小弟初学NIO,做了个控制台聊天工具,不知道代码写的如何,望大神们批评指点. 服务器端,两个线程,一个处理客户端请求和转发消息,另一个处理服务器管理员指令,上代码: package kindz.onlinechat; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.cha

python 开发简单的聊天工具-乾颐堂

python 太强大了,以至于它什么都可以做,哈哈,开个玩笑.但是今天要讲的真的是一个非常神奇的应用. 使用python写一个聊天工具 其实大家平时用的QQ类似的聊天工具,也是使用socket进行聊天,只是它还包含了更加复杂的功能.基本原理是一样的. python实现聊天功能,主要用到了socket模块.下面直接上实例吧 server端 1 2 3 4 5 6 7 8 9 10 11 12 13 import socket s=socket.socket() #建立socket链接 s.bind

python 开发简单的聊天工具

python 太强大了,以至于它什么都可以做,哈哈,开个玩笑.但是今天要讲的真的是一个非常神奇的应用. 使用python写一个聊天工具 其实大家平时用的QQ类似的聊天工具,也是使用socket进行聊天,只是它还包含了更加复杂的功能.基本原理是一样的. python实现聊天功能,主要用到了socket模块.下面直接上实例吧 server端 1 2 3 4 5 6 7 8 9 10 11 12 13 import socket s=socket.socket() #建立socket链接 s.bind

基于Java NIO的多人在线聊天工具源码实现(登录,单聊,群聊)

近来在学习Java NIO网络开发知识,写了一个基于Java NIO的多人在线聊天工具练练手.源码公开在Coding上: https://coding.net/u/hust_wsh/p/MyChat/git ,开发环境是Ubuntu14.04+Eclipse Mars+JDK1.8. 要想编写一个基于Java NIO的多人在线聊天工具,我总结需要以下几方面的地址:客户端服务器模型,Java NIO中的Selector,SocketChannel,ByteBuffer,Collections以及序

python 全双工 socket聊天

自学python一段时间,一直想弄个有意思的东西,所以就拿socket做一个聊天室,可以一对多,一对一全双工聊天.后续可能完善代码在鼓弄一个带gui界面的,比较有逼格. 服务端: 使用socketserver模块,多线程异步处理客户端消息,接受客户消息并转发 既服务端为一个中转站. 加入了 登陆 注册 多人聊天 一对一功能 客户端: 主线程连接服务端,两个子线程分别负责读写 server: SocketServer time ctime threadingtraceback Queue db D

Python Socket 编程——聊天室示例程序

原文:Python Socket 编程--聊天室示例程序 上一篇 我们学习了简单的 Python TCP Socket 编程,通过分别写服务端和客户端的代码了解基本的 Python Socket 编程模型.本文再通过一个例子来加强一下对 Socket 编程的理解. 聊天室程序需求 我们要实现的是简单的聊天室的例子,就是允许多个人同时一起聊天,每个人发送的消息所有人都能接收到,类似于 QQ 群的功能,而不是点对点的 QQ 好友之间的聊天.如下图: 图来自:http://www.ibm.com/de

万字谏言,给那些想学Python的人,建议收藏后细看!

1. 这几天陆续收到很多读者.球友的留言.私信,说要怎么学Python?有没有基础的,偏小白的学习方法?我的回答是:等我统一答复. 小编从不食言,今天就来说说我觉得一个零基础.想转行.一直不得法的人应该如何入门. 万字谏言,给那些想学Python的人,建议收藏后细看!创一个小群,供大家学习交流聊天如果有对学python方面有什么疑惑问题的,或者有什么想说的想聊的大家可以一起交流学习一起进步呀.也希望大家对学python能够持之以恒python爱好群,如果你想要学好python最好加入一个组织,这

Web版的各种聊天工具

直到近期为止,我们经常使用的即时聊天工具(QQ.msn等)了Web版,大家不用下载庞大软件,直接打开网页就能够与自己的好友聊天,非常方便.在此将时汇总 ?????? 便于大家查找 ?????? 节约大家一点时间 此都是官方站点 ?????? 请大家放心使用: 1.先说我们最经常使用的QQ 在线聊天Web版地址: http://webqq.qq.com/ (刚建的 ?????? 现正在測试 ?????? 须要申请 ?????? 日前还不太稳定 ?????? 有待完好) 2.msn在线聊天Web版地

基于文件形式的聊天工具

前因 由于在甲方公司领导要求,在上班时禁止一切的聊天工具的出现.各种封IM软件或者端口.但是开发人员和测试人员相隔半天街,所以,一直想整个简单且不用网络的聊天的工具. 思索半天,遇到以下问题: 我们方的IP地址和甲方人员的不是同网段的 每次交流,除了邮件,就是靠吼 几个人用的系统有几种:xp,win8, win7, mac 网段不一样,某些内网,我们外部不能访问 有以下共同点: 都可以访问某个服务器(因为得时不时看下测试日志) 都会基础的Linux命令 简单,又不用网络的,到底可以做神马呢? 就