用Python写一个类似qq群聊的聊天室

用Python写一个聊天室


功能 : 类似qq群聊

1. 进入聊天室需要输入姓名,姓名不能重复

2. 有人进入聊天室会向其他人发送通知

   xxx 进入了聊天室

3. 一个人发消息,其他人会收到消息

   xxx 说 : xxxxxxxx

4. 某人退出聊天室,其他人也会收到通知

   xxx 退出了聊天室

先看我写的代码的运行结果:

先看我写的代码的运行结果

准备文件:

    tcp_s.py  服务端代码

    tcp_c.py  用户端代码


tcp_s.py 代码


from socket import *

from time import sleep

from select import *

import os

import sys


s = socket(AF_INET,SOCK_STREAM,0) #创建套接字对象


s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #设置端口可重用


s.bind(('0.0.0.0',8888)) #绑定IP和端口号


s.listen(10) #设置最大可连接数


rlist = [s] #设置 读列表

wlist = [] #设置 写列表

xlist = [] #设置 出错列表


while True: #无限接收用户端信息

    rs,ws,xs = select(rlist,wlist,xlist) #将s对象托管给select对象

    for r in rs: #遍历返回的对象列表

        if r is s: #如果对象是 s 套接字对象(服务端本身)

            c,addr = s.accept() #与用户端连接

            rlist.append(c) #将此用户对象保存起来

        else:#如果对象是 c 套接字对象(用户端)

            data = r.recv(1024).decode() #最大一次性接收1024字节,并将接收的内容转化为UTF8

            if not data: #如果传过来没有数据,则认为是用户端已断开

                rlist.remove(r) #将读列表中的此用户删除

            else:#如果有数据传过来,则做相应处理

                data = data.split('_:_') #拆分姓名和说话内容为一个列表

                print(data) #打印列表

                if data[1] == '': #如果没有传过来说话内容,则说明是第一次连接

                    data = data[0] + ' 进入聊天室' #生成 某某进入聊天室 的提示信息

                    for x in rlist: #遍历所有的 套接字对象

                        if x is s: #如果遍历到的套接字对象是服务端自己的对象,则略过

                            pass

                        else:#如果遍历到的套接字对象是用户端的对象,则发送消息(给所有用户发送一条 某某进入聊天室 的消息)

                            x.send(data.encode()) #发送消息

                else: #如果有说话内容传入,则处理

                    data = data[0]+'说:'+data[1] #拆分说话人姓名和说话内容 保存为一个列表

                    for x in rlist: #遍历所有的 套接字对象

                        if x is s: #如果遍历到的套接字对象是服务端自己的对象,则略过

                            pass

                        else:#如果遍历到的套接字对象是用户端的对象,则发送消息(给所有用户发送一条 某某说:XXXXX 的消息)

                            x.send(data.encode()) #发送消息

tcp_s.py代码


tcp_c.py代码


from socket import *

from time import sleep

from select import *

import os


s = socket(AF_INET,SOCK_STREAM,0) #创建套接字对象


addr = ('127.0.0.1',8888) #设置连接地址信息


name = input('请输入姓名>>') #要求输入姓名


s.connect(addr) #连接至服务端

info = name + '_:_' #设置信息的格式

s.send(info.encode()) #将名字发送至服务端


rlist = [s] #设置 读列表

wlist = [] #设置 写列表

xlist = [] #设置 出错列表


pid = os.fork() #开启一个子进程,用于专门接收从服务端传过来的对话数据


if pid == 0: #如果是子进程(用于处理服务端数据的进程)

    while True: #无限接收服务端信息

        rs,ws,xs = select(rlist,wlist,xlist)

        e = 0 #设置一个标记 值 为0

        for r in rs: #遍历所有的套接字对象

            if r is s: #如果遍历到的套接字对象是 本模块的对象

                data = r.recv(1024).decode() #接收从服务器传过来的数据

                if not data: #如果没有数据,则说明服务端要断开

                    e = 1 #设置标记值为1

                else:#如果有数据,则打印

                    print(data)#打印出数据

        if e == 1: #如果标记被改为1,说明要断开,则跳出循环

            break

    else:#循环结束时打印一条消息

        print('子结束')

elif pid > 0: #如果是当前进程(用于发送消息的进程)

    while True: #无限处理要发送的信息

        rs,ws,xs = select(rlist,wlist,xlist)

        e = 0 #设置一个标记 值 为0

        for r in rs: #遍历所有的套接字对象

            if r is s: #如果遍历到的套接字对象是 本模块的对象

                info = input('') #等待用户输入信息

                if not info: #如果没有输入任何信息,则代表用户想要断开连接

                    e = 1 #设置标记值为1

                    info = name + '_:_退出了聊天室' #生成一条给服务端的信息

                    r.send(info.encode()) #最后再给服务端发送一句退出的消息

                else: #如果有输入数据,则处理

                    info = name + '_:_' + info #将数据拼接成相应的格式

                    r.send(info.encode()) #将数据发送给服务端

        if e == 1:  #如果标记被改为1,说明要断开,则跳出循环

            break

    print('父结束') #循环结束时打印一条消息

else:

    print('ERROR',pid)

s.close()

print('结束')

tcp_c.py代码




最后编辑于:2021/03/06作者: 牛逼PHP

发表评论