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

用Python写一个聊天室

功能 : 类似qq群聊

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

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

xxx 进入了聊天室

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

xxx 说 : xxxxxxxx

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

xxx 退出了聊天室

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

6e417299cdd9020d25eebd29f058fe52.png

准备文件:

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()) #发送消息

316c453519581e6c0d25d56180c3f278.png

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('结束')

8204f647d8d29108f59c23f9c33b2ee1.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值