今天用python写了一个简单的群聊程序,分享一下
#server.py
from socket import *
import os,sysdef do_login(s,user,name,addr):
if (name in user) or name == "管理员":
s.sendto("该用户已存在".encode(),addr)
return
s.sendto('ok'.encode(),addr)
msg = '\n欢迎%s进入聊天室'%name
for i in user:
s.sendto(msg.encode(),user[i])
#将用户插入字典
user[name] = addr
def do_chat(s,user,name,text):
msg = '\n%-4s 说:%s'%(name,text)
#发给除了自己以外的所有人
for i in user:
if i != name:
s.sendto(msg.encode(),user[i])
def do_quit(s,user,name):
del user[name]
msg = "\n" + name + '离开了聊天室'
for i in user:
s.sendto(msg.encode(),user[i])
#接受客户端请求并处理
def do_child(s):
#用户存储用户{'zhangsan':('172,168,50,36',7777)}
user = {}
#循环接受各个客户端请求并处理
while True:
msg,addr = s.recvfrom(1024)
msglist = msg.decode().split(' ')
#判断请求类型进行处理
if msglist[0] == 'L':
do_login(s,user,msglist[1],addr)
elif msglist[0] == 'C':
do_chat(s,user,msglist[1],' '.join(msglist[2:]))
else:
do_quit(s,user,msglist[1])
#发送管理员消息
def do_parent(s,addr):
while True:
msg = input("管理员消息:")
msg = 'C 管理员 ' + msg
s.sendto(msg.encode(),addr)
#创建套接字,创建链接,创建父子进程
def main():
#server address
ADDR = ("0.0.0.0",8888)
s = socket(AF_INET,SOCK_DGRAM)
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(ADDR)
#创建父子进程,并且防止僵尸进程
pid = os.fork()
if pid < 0:
sys.exit("创建进程失败")
elif pid == 0:
#创建二级子进程
pid0 = os.fork()
if pid0 < 0:
sys.exit("创建二级进程失败")
elif pid0 == 0:
#执行子进程功能
do_child(s)
else:
os._exit(0)
else:
os.wait()
#执行父进程功能
do_parent(s,ADDR)
if __name__ == '__main__':
main()
#client.py
from socket import *
import os,sys
import signal
#发送消息
def do_child(s,name,addr):
while True:
text = input("发言(quit退出):")
if text.strip() == 'quit':
msg = 'Q ' + name
s.sendto(msg.encode(),addr)
#从子进程中杀死父进程
os.kill(os.getppid(),signal.SIGKILL)
sys.exit("退出聊天室")
else:
msg = 'C %s %s'%(name,text)
s.sendto(msg.encode(),addr)
#接受消息
def do_parent(s):
while True:
msg,addr = s.recvfrom(1024)
print(msg.decode()+"\n发言(quit退出):",end='')
#创建套接字,创建父子进程,登录
def main():
if len(sys.argv) < 3:
print("")
return
HOST = sys.argv[1]
PORT = int(sys.argv[2])
ADDR = (HOST,PORT)
s = socket(AF_INET,SOCK_DGRAM)
#登录
while True:
name = input("请输入姓名:")
msg = 'L ' + name
s.sendto(msg.encode(),ADDR)
data,addr = s.recvfrom(1024)
if data.decode() == 'ok':
print("@进入聊天室@")
break
else:
print(data.decode())
pid = os.fork()
if pid < 0:
sys.exit("创建进程失败")
elif pid == 0:
do_child(s,name,ADDR)
else:
do_parent(s)
if __name__ == '__main__':
main()