import os
import sys
import time
import uuid
from socket import *
import pymysql
DATE_FORMAT_YYYY_MM_DD_HH_MM_SS = '%Y-%m-%d %H:%M:%S'
# 子进程处理客户端请求
def do_login(s, user, name, addr):
# 判断用户是否存在以及用户是否为管理员
cursor.execute("select * from user where name = '" + name + "'")
data = cursor.fetchone()
if (data != None and data[3] == 'on') or name == '管理员':
s.sendto('该用户已存在,请重新输入'.encode(), tuple(list((addr[0], int(addr[1])))))
return
# 用户成功登陆,返回成功信息
s.sendto('OK'.encode(), tuple(list((addr[0], int(addr[1])))))
cursor.execute("select user.name, t.date, t.msg from (select user_id, msg, date from message where date > (select join_date from user where name = '"+name+"')) as t join user on user.id = t.user_id order by t.date")
data_list = cursor.fetchall()
msg = ''
index = 0
for data_temp in data_list:
if index == 0:
msg += '%s 于 %s 发言:%s' % (data_temp[0], data_temp[1], data_temp[2])
else:
msg += '\n%s 于 %s 发言:%s' % (data_temp[0], data_temp[1], data_temp[2])
index += 1
s.sendto(msg.encode(), tuple(list((addr[0], int(addr[1])))))
msg = '\n欢迎 %s 进入聊天室' % name
# 通知所有人
for i in user:
s.sendto(msg.encode(), tuple(list((i[1], int(i[2])))))
# 将用户插入字典
if data != None and data[3] == 'off':
cursor.execute("update user set status = 'on', ip = '"+addr[0]+"', port = '"+addr[1]+"' where name = '" + name + "'")
else:
cursor.execute(
"insert into user values('" + str(uuid.uuid1()) + "', '" + name + "', '" + get_date_str_from_format(
DATE_FORMAT_YYYY_MM_DD_HH_MM_SS) + "', 'on', '" + addr[0] + "', " + addr[1] + ")")
db.commit()
return
# 处理聊天请求
def do_chat(s, user, cmd):
# cmd = ['C','zhang','I','love','China']
name = cmd[1]
ori_msg = ' '.join(cmd[2:])
msg = '\n%s 于 %s 发言:%s' % (name, get_date_str_from_format(DATE_FORMAT_YYYY_MM_DD_HH_MM_SS), ori_msg)
# 将信息发送给出了自己的所有人
for i in user:
if i[0] != cmd[1]:
s.sendto(msg.encode(), tuple(list((i[1], int(i[2])))))
cursor.execute("select id from user where name = '" + name + "'")
data = cursor.fetchone()
user_id = data[0]
cursor.execute("insert into message values('" + str(
uuid.uuid1()) + "', '" + user_id + "', '" + ori_msg + "', '" + get_date_str_from_format(
DATE_FORMAT_YYYY_MM_DD_HH_MM_SS + "')"))
db.commit()
return
# 处理用户离开聊天室请求
def do_quit(s, user, name):
msg = '\n' + name + ' 离开了聊天室'
for i in user:
if i[0] != name:
s.sendto(msg.encode(), tuple(list((i[1], int(i[2])))))
cursor.execute("update user set status = 'off' where name = '"+name+"'")
db.commit()
return
# 子进程处理客户端请求
def do_child(s):
while True:
msg, addr_temp = s.recvfrom(1024)
msg = msg.decode()
cmd = msg.split(' ')
# 字典用来存储用户信息:{name:(ip,port)}
cursor.execute("select name, ip, port from user where status = 'on'")
user = cursor.fetchall()
addr = list(addr_temp)
addr[1] = str(addr[1])
if cmd[0] == 'L':
do_login(s, user, cmd[1], addr)
elif cmd[0] == 'C':
do_chat(s, user, cmd)
elif cmd[0] == 'Q':
do_quit(s, user, cmd[1])
else:
s.sendto('请求错误'.encode(), addr_temp)
# 发送管理员消息
def do_parent(s, addr):
while True:
msg = input('管理员消息:')
msg = 'C 管理员 ' + msg
s.sendto(msg.encode(), tuple(list((addr[0], int(addr[1])))))
s.close()
sys.exit(0)
# 获取指定格式的日期字符串
def get_date_str_from_format(format):
return time.strftime(format, time.localtime(time.time()))
if __name__ == '__main__':
HOST = sys.argv[1]
PORT = (int)(sys.argv[2])
ADDR = (HOST, PORT)
# 创建数据库连接
db = pymysql.connect('localhost', 'root', 'weipeng185261', 'chatroom', charset='utf8')
# 创建游标对象
cursor = db.cursor()
# 使用数据报套接字
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(ADDR)
ADDR = list(ADDR)
ADDR[1] = str(ADDR[1])
# 将管理员加入群聊
cursor.execute("select * from user where name = '管理员'")
data = cursor.fetchone()
if data == None:
cursor.execute("insert into user values('" + str(uuid.uuid1()) + "', '管理员', '" + get_date_str_from_format(
DATE_FORMAT_YYYY_MM_DD_HH_MM_SS) + "', 'on', '" + ADDR[0] + "', " + ADDR[1] + ")")
db.commit()
# 创建子进程
pid1 = os.fork()
if pid1 < 0:
print('创建一级子进程失败')
elif pid1 == 0:
# 创建二级子进程
pid2 = os.fork()
if pid2 < 0:
print('创建二级子进程失败')
elif pid2 == 0:
do_child(s)
else:
# 一级子进程退出,使二级子进程成为孤儿
os._exit(0)
else:
# 等待一级子进程退出
os.wait()
do_parent(s, ADDR)
# 释放资源
cursor.close()
db.close()
基于python实现类似qq群聊功能(源码)
需积分: 50 140 浏览量
2019-03-02
18:08:05
上传
评论 2
收藏 6KB ZIP 举报
GraysonWP
- 粉丝: 59
- 资源: 12
最新资源
- DTS03K16-VB一款N-Channel沟道SOT23的MOSFET晶体管参数介绍与应用说明
- pcm-task-record-report.sql
- DTS03K16A-VB一款SOT23封装N-Channel场效应MOS管
- DTM9906-VB一款N+P-Channel沟道SOP8的MOSFET晶体管参数介绍与应用说明
- DTM4953-VB一款SOP8封装2个P-Channel场效应MOS管
- ADC0804、DS18B20、LCD1602的C代码
- DTM4407-VB一款P-Channel沟道SOP8的MOSFET晶体管参数介绍与应用说明
- 通信管道水平定向钻穿越建设规范.doc
- 通信管道监理大纲.doc
- 基于Java的招生信息管理系统设计源码
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈