基于python的socket和fork模块实现简易聊天室
服务器端
‘’’
名称:网络聊天室
环境:Python3.5
技术:socket fork
‘’’
import socket
import os
import sys
创建网络连接
def main():
# 创建UDP套接字
server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 设置端口复用
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 绑定地址
ADDRESS = (‘0.0.0.0’,8888)
server.bind(ADDRESS)
# 创建多进程,子进程负责管理员喊话,父进程和客户端交互
pid = os.fork()
if pid < 0:
# 一旦进程创建失败就结束
print('进程创建失败')
return
# 子进程负责管理员发送消息
elif pid == 0:
print('负责管理员喊话的进程')
# 父进程处理客户端的各种请求
else:
doRequest(server)
处理客户端请求的函数
def doRequest(server):
# 定义存储结构
user = {}
while True:
# 收消息
message,addr = server.recvfrom(1024)
# msgList : [‘L’,‘金毛狮王’]
msgList = message.decode().split(’ ')
if msgList[0] == ‘L’:
doLogin(server,user,msgList[1],addr)
elif msgList[0] == ‘C’:
# msgList: [‘C’,‘name’,‘你好’,‘步惊云’]
content = ’ '.join(msgList[2:])
# 发给其他所有成员
doChat(server,content,user,msgList[1])
elif msgList[0] == ‘Q’:
doQuit(server,msgList[1],user)
进入到聊天室请求处理函数
def doLogin(server,user,name,addr):
# {name:addr}
# 判断姓名是否存在
if (name in user) or name == ‘管理员’:
server.sendto(‘该用户已存在’.encode(),addr)
return
# 名字不存在,发送OK给客户端,允许进入
server.sendto(‘OK’.encode(),addr)
# 先通知其他人
message = ‘欢迎 %s 进入聊天室’ % name
for u in user:
server.sendto(message.encode(),user[u])
# 加入存储结构user中
user[name] = addr
聊天函数(把消息发给其他成员)
def doChat(server,content,user,name):
# 丰满消息
message = ‘%s说:%s’ % (name,content)
for u in user:
# 发给其他成员
if u != name:
server.sendto(message.encode(),user[u])
处理客户端退出函数
def doQuit(server,name,user):
# 通知其他成员
message = ‘%s 退出了聊天室’ % name
for u in user:
if u != name:
server.sendto(message.encode(),user[u])
# 给退出者本人发消息
else:
server.sendto(b’EXIT’,user[name])
# 从存储结构中删除
del user[name]
if name == “main”:
main()
客户端
import socket
import os
import sys
创建套接字函数
def main():
# 从命令行输入IP地址和端口号
if len(sys.argv) < 3:
print(‘参数错误’)
return
ADDRESS = (sys.argv[1],int(sys.argv[2]))
# 创建UDP套接字
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 接收用户输入,包装后发给服务端
while True:
name = input(‘请输入姓名:’)
message = 'L ’ + name
# 向服务器发送消息
client.sendto(message.encode(),ADDRESS)
# 接收服务器反馈
data,addr = client.recvfrom(1024)
if data.decode() == ‘OK’:
print(‘您已进入聊天室’)
break
else:
# 打印不允许进入的原因
print(data.decode())
# 创建进程,子进程发消息,父进程收消息
pid = os.fork()
if pid < 0:
sys.exit('创建进程失败')
# 子进程发消息
elif pid == 0:
sendMsg(client,name,ADDRESS)
# 父进程收消息
else:
recvMsg(client)
子进程发消息函数
def sendMsg(client,name,ADDRESS):
# 发消息给服务端,服务端再进行转发
while True:
content = input(‘请发言(quit退出):’)
# 退出
if content == ‘quit’:
message = 'Q ’ + name
client.sendto(message.encode(),ADDRESS)
sys.exit(‘退出聊天室’)
# 包装消息
message = ‘C %s %s’ % (name,content)
client.sendto(message.encode(),ADDRESS)
父进程收消息函数
def recvMsg(client):
while True:
message,addr = client.recvfrom(1024)
# 父进程退出
if message.decode() == ‘EXIT’:
os._exit(0)
print(message.decode())
if name == ‘main’:
main()