历经多天的努力,查阅了许多大佬的博客后终于实现了一个简易的微信O(∩_∩)O~~
import socket
import threading
from pandas import *
import pymysql
import csv
# 创建DataFrame对象
# 存储用户数据的表(状态没用上。。。)
df = pandas.DataFrame([['whs','123','1']], columns=['account','password','state'], index=[0])
df.to_csv('user.csv',index=0)
#储存好友关系
df = pandas.DataFrame([['whs','wyl']], columns=['friend1','friend2'], index=[0])
df.to_csv('link.csv',index=0)
#存储待添加好友关系的表
df = pandas.DataFrame([['whs','@@@']], columns=['friend1','friend2'], index=[0])
df.to_csv('to_be_link.csv',index=0)
#储存在线人
df = pandas.DataFrame([['whs','127.0.0.1']], columns=['name','addr'], index=[0])
df.to_csv('onlinelist.csv',index=0)
#在客户端用于存储最近收到的信息
df = pandas.DataFrame([['@@@','@@@','@@@']], columns=['name','title','message'], index=[0])
df.to_csv('resent_message.csv',index=0)
print(df)
def addonlinelist(name,addr,connectionSocket):
onlinelist = read_csv('onlinelist.csv', dtype={'name': str,'addr': str})
#打开csv文件并指定格式
flag = onlinelist[onlinelist.name == name].shape[0]
#如果数据不存在
if(flag!=0):
k = onlinelist[onlinelist.name == name].index.tolist()[0]
onlinelist=onlinelist.drop(k)
#如果有之前的残余数据则删去
connect_list.append(connectclient(name,addr,connectionSocket))
new = DataFrame({'name': name, 'addr': str(addr)},index=[0])
onlinelist = onlinelist.append(new,ignore_index=True)
#存储,并且忽略index
onlinelist.to_csv('onlinelist.csv',index=0)
语法与之前几乎一样,不做赘述
def adduser(name,passwd,status):#添加使用者
user = read_csv('user.csv', dtype={'name': str,'passwd': str})
flag = user[user.name == name].shape[0]
if(flag != 0):
return False
new = DataFrame({'name': name, 'passwd': passwd, 'status': status}, index=[0])
user = user.append(new, ignore_index=True)
user.to_csv('user.csv',index=0)
return True
def checkexist(name):#查看用户是否存在
user = read_csv('user.csv', dtype={'name': str,'passwd': str})
flag = user[user.name==name].shape[0]
if(flag==0):
return False
else:
return True
def checkuser(name,passwd):#查看用户名密码正确性
user = read_csv('user.csv', dtype={'name': str,'passwd': str})
if(passwd==str(user[user.name == name].passwd.tolist()[0])):
return True
else:
return False
def deletefriend(name1,name2):#删除好友
link = read_csv('link.csv', dtype={'friend1': str,'friend2': str})
flag = link[((link.friend1 == name1) & (link.friend2 == name2)) | ((link.friend1 == name2) & (link.friend2 == name1))].shape[0]
if(flag == 0):
return 'not_exist'
k = link[((link.friend1 == name1) & (link.friend2 == name2)) | ((link.friend1 == name2) & (link.friend2 == name1))].index.tolist()[0]
link = link.drop(k)
link.to_csv('link.csv', index=0)
return 'delete_ok'
def addfriend(name1,name2):#添加好友
if(isfriend(name1,name2)==True):
return 'already_friend'
to_be_link = read_csv('to_be_link.csv', dtype={'friend1': str,'friend2': str})
user = read_csv('user.csv')
flag = user[(user.name == name2)].shape[0]
if(flag == 0):
return 'not_exist'
new = DataFrame({'friend1':name1, 'friend2':name2}, index = [0])
to_be_link = to_be_link.append(new,ignore_index=True)
to_be_link.to_csv('to_be_link.csv',index=0)
return 'add_to_be'
def acceptfriend(name1,name2):#接收好友请求
link = read_csv('link.csv', dtype={'friend1': str,'friend2': str})
to_be_link = read_csv('to_be_link.csv', dtype={'friend1': str,'friend2': str})
print(type(name1))
print(type(name1))
if (istobefriend(name1, name2) == False):
return 'not_exist'
print('tttttttttt')
new = DataFrame({'friend1': name1, 'friend2': name2}, index=[0])
link = link.append(new, ignore_index=True)
link.to_csv('link.csv', index=0)
k = to_be_link[((to_be_link.friend1 == name1) & (to_be_link.friend2 == name2)) | ((to_be_link.friend1 == name2) & (to_be_link.friend2 == name1))].index.tolist()[0]
to_be_link = to_be_link.drop(k)
to_be_link.to_csv('to_be_link.csv',index=0)
# connectionSocket.send(('添加好友成功').encode())
return 'accept_ok'
def delete_to_be_friend(name1,name2):#从待接收列表中删除
to_be_link = read_csv('to_be_link.csv', dtype={'friend1': str,'friend2': str})
k = to_be_link[((to_be_link.friend1 == name1) & (to_be_link.friend2 == name2)) | (
(to_be_link.friend1 == name2) & (to_be_link.friend2 == name1))].index.tolist()[0]
to_be_link = to_be_link.drop(k)
to_be_link.to_csv('to_be_link.csv', index=0)
def isfriend(name1,name2):#判断两个人是否是好友
link = read_csv('link.csv')
flag = link[((link.friend1 == name1) & (link.friend2 == name2)) | ((link.friend1 == name2) & (link.friend2 == name1))].shape[0]
if (flag == 0):
return False
return True
def istobefriend(name1,name2):#判断是否发起好友请求
to_be_link = read_csv('to_be_link.csv', dtype={'friend1': str,'friend2': str})
flag = to_be_link[((to_be_link.friend1 == name1) & (to_be_link.friend2 == name2)) | (
(to_be_link.friend1 == name2) & (to_be_link.friend2 == name1))].shape[0]
if (flag == 0):
return False
return True
def printlist(name):#打印好友列表
link = read_csv('link.csv', dtype={'friend1': str,'friend2': str})
k = link[(link.friend1 == name)|(link.friend2 == name)].shape[0]
if(k==0):
return '.'
# connectionSocket.send(('您的好友列表如下').encode())
message = '/'.join(link[link.friend1 == name].friend2.tolist()+link[link.friend2 == name].friend1.tolist())
# connectionSocket.send(message.encode())
print(message)
return '/' + message
def printtobelist(name):#打印待同意好友列表
to_be_link = read_csv('to_be_link.csv', dtype={'friend1': str,'friend2': str})
k = to_be_link[(to_be_link.friend2 == name)].shape[0]
if (k == 0):
return '.'
# connectionSocket.send(('有如下的人要添加你为好友,想接受则输入该好友名字,否则输入/exit/退出').encode())
print(to_be_link[to_be_link.friend2 == name].friend1.tolist())
message = '/'.join(to_be_link[to_be_link.friend2 == name].friend1.tolist())
return '/'+message
'''
2.0 报头
服务器和客服端之间,使用自己定义的报头进行通信
协议整体大致呈树形结构,收到消息后进行一层层解析,得到最终的结果。
2.1 注册
注册发送
root/reg/name/passwd
注册接收
register_ok(注册成功),register_error(用户名以及存在)
2.2 登录
登录发送
root/reg/name/passwd
登录接收
noPassword,user,noAccount
2.3 获取好友列表
获取已经有的好友的列表
root/friend_op(操作类型)/print_friend_list(操作方式)/myname
获取向你提出好友申请的人的列表
root/friend_op(操作类型)/print_to_be_list(操作方式)/myname
2.4 添加好友
root/friend_op(操作类型)/add(操作方式)/myname/othername
服务器端发出的信息
root/friend_op/(delete)(add)/othername/state('not_exist''delete_ok''already_friend''not_exist''add_to_be')
用户不存在 成功
2.5 好友请求回复
root/friend_op(操作类型)/accept(操作方式)/myname/othername
2.6 删除好友
root/friend_op(操作类型)/delete(操作方式)/myname/othername
2.7 [服务器]好友请求
root/friend_op(操作类型)/add(操作方式)/othername
2.8 [服务器]好友请求结果
root/friend_op/add/othername/state('not_exist''already_friend''add_to_be')
状态分为分为该用户不存在,你们已经是朋友,成功发出好友请求三种。
2.9 发送消息和文件
从客服端传输信息的格式
root/chat/message/from_name/to_name/message_content
客户端发送文件的格式
root/chat/file/from_name/to_name
传输是否在线的系统消息
2.10 [服务器]消息和文件
root/chat/file/from_name/begin(end)
root/chat/message/to_name/message_content
2.11 离线
root/chat/info/system_message/from_name
(判断是否在线后发送)
'''
while True:
connectionSocket, addr = serverSocket.accept()
print(addr)
# connectionSocket.send(('连接主机成功').encode())
# 每当客户端连接后启动一个线程为该客户端服务
threading.Thread(target=server_target, args=(connectionSocket, addr,)).start()
serverSocket.close()
if __name__ == '__main__':
t = Client()
main_login()
def server_target(connectionSocket, addr):#服务器主要函数
while(1):
message = connectionSocket.recv(1024).decode()
deal_message = message.split('/')
print(deal_message)
lenth = len(deal_message)
print(deal_message[0])
if(deal_message[0]=='un_root'):#收到则退出
connectionSocket.send(('un_root').encode())
break
else:
if(deal_message[1] == 'login'):#进行登录操作
account = deal_message[2]
password = deal_message[3]
if(checkexist(account)==False):
connectionSocket.send(('noAccount').encode())
elif(checkuser(account,password)==False):
connectionSocket.send(('noPassword').encode())
else:
connectionSocket.send(('user').encode())
addonlinelist(account, addr, connectionSocket)
elif(deal_message[1] == 'register'):#进行注册
account = deal_message[2]
password = deal_message[3]
if(adduser(account, password, 1)):
connectionSocket.send(('register_ok').encode())
addonlinelist(account, addr, connectionSocket)
else:
connectionSocket.send(('register_error').encode())
elif(deal_message[1] == 'chat'):#进行信息交互
type = deal_message[2]
account = deal_message[3]
friend_account = deal_message[4]
if(type == 'file'):
for clients in connect_list:
if (str(clients.name) == str(friend_account)):
print(('root/chat/' + type + '/' + account + '/begin'))
try:
clients.connectionSocket.send(
('root/chat/' + type + '/' + account + '/begin').encode())
except:
pass
# 申请相同大小的空间存放发送过来的文件名与文件大小信息
fileinfo_size = struct.calcsize('128sl')
# 接收文件名与文件大小信息
buf = connectionSocket.recv(fileinfo_size)
for clients in connect_list:
if (str(clients.name) == str(friend_account)):
print(('root/chat/' + type + '/' + account + '/begin'))
try:
clients.connectionSocket.send(buf)
except:
pass
# 判断是否接收到文件头信息
if buf:
# 获取文件名和文件大小
filename, filesize = struct.unpack('128sl', buf)
fn = filename.strip(b'\00')
fn = fn.decode()
print ('file new name is {0}, filesize if {1}'.format(str(fn), filesize))
recvd_size = 0 # 定义已接收文件的大小
# 存储在该脚本所在目录下面
print ('start receiving...')
# 将分批次传输的二进制流依次写入到文件
while not (recvd_size == filesize):
if filesize - recvd_size > 1024:
data = connectionSocket.recv(1024)
recvd_size += len(data)
else:
data = connectionSocket.recv(filesize - recvd_size)
recvd_size = filesize
for clients in connect_list:
if (str(clients.name) == str(friend_account)):
print(data)
try:
clients.connectionSocket.send(data)
except:
pass
print('end receive...')
elif(type == 'message'):
message = deal_message[5]+'/'+deal_message[6]
isfind = False
for clients in connect_list:#遍历list发送信息
if(str(clients.name) == str(friend_account)):
print(('root/chat/' + type + '/' + account + '/' + message))
try:
clients.connectionSocket.send(('root/chat/'+type+'/'+account+'/'+ message).encode())
isfind = True
except:
pass
if(isfind == False):
connectionSocket.send(('root/chat/info/'+friend_account+'/'+'对方不在线无法接收你的消息').encode())
# print(('root/chat/'+friend_account+'/'+account+'/'+'对方不在线无法接收你的消息'))
elif(deal_message[1] == 'friend_op'):#对于好友命令进行操作
print(deal_message[2])
if(deal_message[2] == 'add'):
account = deal_message[3]
friend_account = deal_message[4]
connectionSocket.send(('root/friend_op/add/' + friend_account + '/' + addfriend(account, friend_account)).encode())
elif(deal_message[2] == 'accept'):
account = deal_message[3]
friend_account = deal_message[4]
acceptfriend(account, friend_account)
connectionSocket.send(('root/friend_op/accept/' + friend_account).encode())
elif(deal_message[2] == 'delete'):
account = deal_message[3]
friend_account = deal_message[4]
connectionSocket.send(('root/friend_op/delete/'+friend_account+'/'+deletefriend(account,friend_account)).encode())
elif(deal_message[2] == 'reject'):
account = deal_message[3]
friend_account = deal_message[4]
delete_to_be_friend(account,friend_account)
elif(deal_message[2] == 'print_friend_list'):
account = deal_message[3]
print(printlist(account))
connectionSocket.send((('root/friend_op/print_friend_list'+printlist(account)).strip('.')).encode())
print(('root/friend_op/print_friend_list'+printlist(account)).strip('.'))
elif(deal_message[2] == 'print_to_be_friend_list'):
account = deal_message[3]
connectionSocket.send((('root/friend_op/print_to_be_friend_list' + printtobelist(account)).strip('.')).encode())
print(('root/friend_op/print_to_be_frined_list' + printtobelist(account)).strip('.'))
class Client(object):
def __init__(self):
self.connecntsocket = socket(AF_INET, SOCK_STREAM)
self.connecntsocket.connect(('127.0.0.1', 12000))
#连接ip和端口
self.myqueue=queue.Queue()
self.name = ''
self.flag = True
self.friend_list = []
self.to_be_friend_list = []
def read_from_server(self):
while True:
if(self.flag==False):
break
message = self.connecntsocket.recv(1024).decode()
print(message)
deal_message = message.split('/')
print(deal_message)
lenth = len(deal_message)
print(deal_message[0])
if(deal_message[0] == 'un_root'):
break
else:
if(deal_message[1] == 'chat'):
if(deal_message[2] == 'message'):#处理信息,放到该放的地方
print('message')
friend_account = deal_message[3]
friend_title = deal_message[4]
friend_message = deal_message[5]
resent_message = read_csv('resent_message.csv')
new = DataFrame({'name': friend_account, 'title': friend_title, 'message': friend_message}, index=[0])
resent_message = resent_message.append(new, ignore_index=True)
resent_message.to_csv('resent_message.csv', index=0)
isfind = False
for Chat_window in Chat_list:
if(Chat_window.name == friend_account):
try:
Chat_window.insert_message(friend_title,friend_message)
except:
pass
isfind = True
if(isfind == False):#to be continue
pass
elif(deal_message[2] == 'file'):
if(deal_message[4] == 'begin'):
# 申请相同大小的空间存放发送过来的文件名与文件大小信息
fileinfo_size = struct.calcsize('128sl')
# 接收文件名与文件大小信息
buf = t.connecntsocket.recv(fileinfo_size)
# 判断是否接收到文件头信息
if buf:
# 获取文件名和文件大小
filename, filesize = struct.unpack('128sl', buf)
fn = filename.strip(b'\00')
fn = fn.decode()
print ('file new name is {0}, filesize if {1}'.format(str(fn), filesize))
recvd_size = 0 # 定义已接收文件的大小
# 存储在该脚本所在目录下面
fp = open('./' + str('new' + fn), 'wb')
print ('start receiving...')
# 将分批次传输的二进制流依次写入到文件
while not recvd_size == filesize:
if filesize - recvd_size > 1024:
data = t.connecntsocket.recv(1024)
recvd_size += len(data)
else:
data = t.connecntsocket.recv(filesize - recvd_size)
recvd_size = filesize
fp.write(data)
fp.close()
print ('end receive...')
elif(deal_message[2] == 'info'):
friend_account = deal_message[3]
system_info = deal_message[4]
isfind = False
for Chat_window in Chat_list:
if (Chat_window.name == friend_account):
Chat_window.insert_info(system_info)
isfind = True
if (isfind == False):
pass
elif(deal_message[1] == 'friend_op'):
if(deal_message[2] == 'delete'):
if(deal_message[4] == 'not_exist'):
self.creatbox(deal_message[3] + '不在您的好友列表中')
elif(deal_message[4] == 'delete_ok'):
self.creatbox('已经把'+deal_message[3]+'从您的好友列表删除')
elif(deal_message[2] == 'add'):
if(deal_message[4] == 'already_friend'):
self.creatbox('你和' + deal_message[3]+'已经是好友了')
elif(deal_message[4] == 'not_exist'):
self.creatbox('用户' + deal_message[3] + '不存在')
elif(deal_message[4 == 'add_to_be']):
self.creatbox('已经发送对'+deal_message[3]+'的好友申请')
elif(deal_message[2] == 'accept'):
self.creatbox('已经把' + deal_message[3] + '添加到您的好友列表')
elif(deal_message[2] == 'print_friend_list'):
self.friend_list = deal_message[3:lenth]
elif(deal_message[2] == 'print_to_be_friend_list'):
self.to_be_friend_list = deal_message[3:lenth]
print(1)
def creatbox(self,message):
tkinter.messagebox.showinfo(title='miniWechat', message=message)
def terminate(self):
self.flag = False
def run(self):
self.flag = True
self.THD = threading.Thread(target=self.read_from_server, args=()).start()
class Login(object):
def __init__(self):
# 创建主窗口,用于容纳其它组件
self.root = Tk()
# 给主窗口设置标题内容
self.root.title("miniWechat")
#自定义关闭按钮,不然关闭GUI后socket还在运行中
self.root.protocol('WM_DELETE_WINDOW', self.my_close)
self.root.geometry('450x300')
#运行代码时记得添加一个gif图片文件,不然是会出错的
self.canvas = tkinter.Canvas(self.root, height=300, width=500)#创建画布
self.image_file = tkinter.PhotoImage(file='1572079024477.gif')
self.image = self.canvas.create_image(0,0, anchor='nw', image=self.image_file)#将图片置于画布上
self.canvas.grid(row=0, column=0)#放置画布(为上端)
#创建一个`label`名为`Account: `
self.label_account = tkinter.Label(self.root, text='Account: ')
#创建一个`label`名为`Password: `
self.label_password = tkinter.Label(self.root, text='Password: ')
# 创建一个账号输入框,并设置尺寸
self.input_account = tkinter.Entry(self.root, width=30)
# 创建一个密码输入框,并设置尺寸
self.input_password = tkinter.Entry(self.root, show='*', width=30)
# 创建一个登录系统的按钮
self.login_button = tkinter.Button(self.root, command = self.backstage_interface, text = "Login", width=10)
# 创建一个注册系统的按钮
self.siginUp_button = tkinter.Button(self.root, command = self.siginUp_interface, text = "Sign up", width=10)
# 完成布局
def gui_arrang(self):
self.label_account.place(x=60, y= 170)
self.label_password.place(x=60, y= 195)
self.input_account.place(x=135, y=170)
self.input_password.place(x=135, y=195)
self.login_button.place(x=140, y=235)
self.siginUp_button.place(x=240, y=235)
# 进入注册界面
def siginUp_interface(self):
# self.root.destroy()
account = self.input_account.get()
password = self.input_password.get()
verifyResult =self.reg_verifyAccountData(account,password)
if(verifyResult == 'register_ok'):
t.name = account
self.start()
else:
tkinter.messagebox.showinfo(title='注册信息提示', message='用户名已经被使用')
# 进行登录信息验证
def backstage_interface(self):
account = self.input_account.get()#.ljust(10," ")
password = self.input_password.get()#.ljust(10," ")
#对账户信息进行验证,普通用户返回user,管理员返回master,账户错误返回noAccount,密码错误返回noPassword
verifyResult =self.log_verifyAccountData(account,password)
if verifyResult=='master':
self.root.destroy()
tkinter.messagebox.showinfo(title='miniWechat', message='进入管理界面')
elif verifyResult=='user':
t.name = account
self.start()
elif verifyResult=='noAccount':
tkinter.messagebox.showinfo(title='miniWechat', message='该账号不存在请重新输入!')
elif verifyResult=='noPassword':
tkinter.messagebox.showinfo(title='miniWechat', message='账号/密码错误请重新输入!')
def run(self):
self.root.run()
def start(self):
self.root.destroy()
t.run()
main_user()
def log_verifyAccountData(self,account,password):
#向服务器发送信息
t.connecntsocket.send(('root/'+'login'+'/'+account+'/'+password).encode())
sentense = t.connecntsocket.recv(2048).decode()
print(sentense)
return sentense
def reg_verifyAccountData(self,account,password):
t.connecntsocket.send(('root/'+'register'+'/'+account+'/'+password).encode())
sentense = t.connecntsocket.recv(2048).decode()
print(sentense)
return sentense
def my_close(self):
t.connecntsocket.send(('un_root').encode())
self.root.destroy()
sleep(1)
t.connecntsocket.close()
class User(object):
def __init__(self):
self.tk = Tk()
self.tk.title('用户界面')
self.tk.protocol('WM_DELETE_WINDOW', self.my_close)
self.button_pos = 280
self.friend_list = [None]*80
self.friend_list_len = 0
self.to_be_friend_list = [None] * 80
self.to_be_friend_list_len = 0
#好友列表
self.friend_area = Canvas(self.tk, bg='pink')
self.friend_area.place(x=5, y=260, heigh=340, width=340)
self.friend_text = scrolledtext.ScrolledText(self.friend_area)
self.friend_text.place(x=5, y=5, heigh=340, width=330)
#待添加好友列表
self.to_be_friend_area = Canvas(self.tk,bg='pink')
self.to_be_friend_area.place(x=5, y=650, heigh=340, width=340)
self.to_be_friend_text = scrolledtext.ScrolledText(self.to_be_friend_area)
self.to_be_friend_text.place(x=5, y=5, heigh=340, width=340)
self.tk.geometry('350x1000')
# 运行代码时记得添加一个gif图片文件,不然是会出错的
self.canvas = tkinter.Canvas(self.tk, height=200, width=350) # 创建画布
self.image_file = tkinter.PhotoImage(file='1572079024477.gif')
self.image = self.canvas.create_image(0, 0, anchor='nw', image=self.image_file) # 将图片置于画布上
self.canvas.place(x=0,y=0)#pack(side='top') # 放置画布(为上端)
# self.friend_list = tkinter.Button(self.tk, text='添加好友', bg='skyblue', command=self.to_chat, font=('Arial', 16))
# self.friend_list.place(x=20, y=280)
#添加TEXT文本
self.add_friend_label = tkinter.Label(self.tk, text='名字 ')
self.friend_list_label = tkinter.Label(self.tk, text='好友列表 ',bg='blue',fg='black',font=("华文行楷", 16),width=32,height=2)
self.to_be_friend_list_label = tkinter.Label(self.tk, text='待通过的好友请求 ',bg='blue',fg='black',font=("华文行楷", 16),width=32,height=2)
#添加输入框
self.input_friend_name = tkinter.Entry(self.tk, width=20)
#添加按钮
self.add_friend_button = tkinter.Button(self.tk, command=self.add_friend, text="确认添加", width=6)
self.delete_friend_button = tkinter.Button(self.tk, command=self.delete_friend, text="确认删除", width=6)
self.refresh_all_button = tkinter.Button(self.tk, command=self.refresh_all, text="刷新列表", width=10)
#放到指定位置
self.add_friend_label.place(x=0,y=181)
self.input_friend_name.place(x=35,y=182)
self.add_friend_button.place(x=180,y=180)
self.delete_friend_button.place(x=230, y=180)
self.refresh_all_button.place(x=280,y=180)
self.friend_list_label.place(x=10,y=210)
self.to_be_friend_list_label.place(x=10,y=600)
self.refresh_friend_list()
self.refresh_to_be_friend_list()
def refresh_to_be_friend_list(self):
self.to_be_friend_text.delete(0.0,END)
t.connecntsocket.send(('root/friend_op/print_to_be_friend_list/' + t.name).encode())
time.sleep(0.1)
self.to_be_deal_message = t.to_be_friend_list # deal_message中存放所有名字
print(self.to_be_deal_message)
self.to_be_friend_list_len = len(self.to_be_deal_message)
for i in range(0, self.to_be_friend_list_len):
self.create_to_be_friend_bottun(i, self.to_be_deal_message[i])
def refresh_friend_list(self):#刷新好友列表
self.friend_text.delete(0.0,END)
t.connecntsocket.send(('root/friend_op/print_friend_list/'+t.name).encode())
time.sleep(0.1)
self.deal_message = t.friend_list#deal_message中存放所有名字
self.friend_list_len = len(self.deal_message)
for i in range(0, self.friend_list_len):
self.create_friend_bottun(i, self.deal_message[i])
def create_to_be_friend_bottun(self, i, name):
self.to_be_friend_list[i] = tkinter.Button(self.to_be_friend_text, text=name, bg='skyblue', command=lambda:self.whether_accpet(name), font=('Arial', 16), width=33, height=1)
self.to_be_friend_text.window_create(END, window=self.to_be_friend_list[i])
def create_friend_bottun(self,i,name):
self.friend_list[i] = tkinter.Button(self.friend_text, text=name, bg='skyblue', command=lambda:self.to_chat(name), font=('Arial', 16), width=23, height=1)
self.friend_text.window_create(END, window=self.friend_list[i])
def whether_accpet(self,name):
flag = messagebox.askokcancel(title='miniWechat', message=('是否接受' + name + '的好友请求?'))
if (flag == True):
t.connecntsocket.send(('root/friend_op/accept/'+t.name+'/'+name).encode())
else:
t.connecntsocket.send(('root/friend_op/reject/'+t.name+'/'+name).encode())
def to_chat(self,name):
print(name)
main_chat(name)
def refresh_all(self):
self.refresh_to_be_friend_list()
self.refresh_friend_list()
def delete_friend(self):
name = self.input_friend_name.get()
t.connecntsocket.send(('root/friend_op/delete/' + t.name + '/' + name).encode())
def add_friend(self):
name = self.input_friend_name.get()
print(type(name))
t.connecntsocket.send(('root/friend_op/add/'+t.name+'/'+name).encode())
print(name)
def handler(self,event, top, lb):
"""事件处理函数"""
content = lb.get(lb.curselection())
return messagebox.showinfo(title="Hey, you got me!", message="I am {0}".format(content), parent=top)
def handler_adaptor(self,fun, **kwds):
"""事件处理函数的适配器,相当于中介"""
return lambda event, fun=fun, kwds=kwds: fun(event, **kwds)
def run(self):
self.tk.mainloop()
def my_close(self):
t.connecntsocket.send(('un_root').encode())
self.tk.destroy()
sleep(1)
t.connecntsocket.close()
class Chat(object):
def __init__(self,name):
self.root = Toplevel()
self.name = name
self.root.title(name)
self.root.protocol('WM_DELETE_WINDOW', self.my_close)
'''创建分区'''
self.f_msglist = Frame(self.root,height=300, width=300) # 创建<消息列表分区 >
self.f_msgsend = Frame(self.root,height=300, width=300) # 创建<发送消息分区 >
self.f_floor = Frame(self.root,height=100, width=300) # 创建<按钮分区>
self.f_right = Frame(self.root,height=700, width=100) # 创建<图片分区>
'''创建控件'''
self.txt_msglist = Text(self.f_msglist) # 消息列表分区中创建文本控件
self.txt_msglist.tag_config('green', foreground='blue') # 消息列表分区中创建标签
self.txt_msgsend = Text(self.f_msgsend) # 发送消息分区中创建文本控件
self.txt_msgsend.bind('' , self.msgsendEvent) # 发送消息分区中,绑定‘UP’键与消息发送。
'''txt_right = Text(f_right) #图片显示分区创建文本控件'''
self.button_send = Button(self.f_floor, text='发送', command=self.msgsend) # 按钮分区中创建按钮并绑定发送消息函数
self.button_cancel = Button(self.f_floor, text='取消', command=self.cancel) # 分区中创建取消按钮并绑定取消函数
self.button_send_file = Button(self.f_floor, text='上传', command=self.filesend)
self.button_resent_message = Button(self.f_floor, text='最近消息', command=self.get_resent_message)
# self.photo = PhotoImage(file='1572079024477.gif')
# self.label = Label(self.f_right, image=self.photo) # 右侧分区中添加标签(绑定图片)
self.label = Label(self.f_right)
# self.label.image = self.photo
self.canvas = Canvas(self.root, height=300, width=500) # 创建画布
self.image_file = PhotoImage(file='15720790244771.gif')
self.image = self.canvas.create_image(0, 0, anchor='nw', image=self.image_file) # 将图片置于画布上
self.canvas.grid(row=1, column=1) # 放置画布(为上端)
'''分区布局'''
self.f_msglist.grid(row=0, column=0) # 消息列表分区
self.f_msgsend.grid(row=1, column=0) # 发送消息分区
self.f_floor.grid(row=2, column=0) # 按钮分区
self.f_right.grid(row=0, column=1, rowspan=3) # 图片显示分区
self.txt_msglist.grid() # 消息列表文本控件加载
self.txt_msgsend.grid() # 消息发送文本控件加载
self.button_send.grid(row=0, column=0, sticky=W) # 发送按钮控件加载
self.button_cancel.grid(row=0, column=1, sticky=W) # 取消按钮控件加载
self.button_send_file.grid(row=0, column=2, sticky=W)
self.button_resent_message.grid(row=0, column=3, sticky=W)
self.label.grid() # 右侧分区加载标签控件
def insert_message(self,massage_title,massage_content):
self.txt_msglist.insert(END, massage_title+'\n', 'green')
self.txt_msglist.insert(END, massage_content)
def insert_info(self,system_info):
self.txt_msglist.insert(END, system_info + '\n', 'red')
def get_resent_message(self):
resent_message = read_csv('resent_message.csv')
k = resent_message[resent_message.name == self.name].shape[0]
if (k == 0):
return
title1 = '/'.join(resent_message[resent_message.name == self.name].title.tolist())
message1 = '/'.join(resent_message[resent_message.name == self.name].message.tolist())
title = title1.split('/')
message = message1.split('/')
self.txt_msgsend.delete(0.0,END)
lenth = len(title)
for i in range(0,lenth):
self.txt_msglist.insert(END, title[i] + '\n', 'green')
self.txt_msglist.insert(END, message[i])
def msgsend(self):
self.msg = t.name + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
self.txt_msglist.insert(END, self.msg + '\n', 'green') # 添加时间
self.txt_msglist.insert(END, self.txt_msgsend.get('0.0', END)) # 获取发送消息,添加文本到消息列表
message =self.msg+'/'+self.txt_msgsend.get('0.0', END)
mm=('root/chat/'+t.name+'/'+self.name+'/'+message)
print(mm)
t.connecntsocket.send(('root/chat/message/'+t.name+'/'+self.name+'/'+message).encode())
resent_message = read_csv('resent_message.csv')
new = DataFrame({'name': self.name, 'title': self.msg + '\n', 'message': self.txt_msgsend.get('0.0', END)}, index=[0])
resent_message = resent_message.append(new, ignore_index=True)
resent_message.to_csv('resent_message.csv', index=0)
self.txt_msgsend.delete('0.0', END) # 清空发送消息
'''定义取消发送 消息 函数'''
def filesend(self):
filepath = self.txt_msgsend.get('0.0', END)
self.txt_msgsend.delete('0.0', END) # 清空发送消息
t.connecntsocket.send(('root/chat/file/'+t.name+'/'+self.name+'/begin').encode())
filepath = filepath.strip('\n')
if os.path.isfile(filepath):
# 定义定义文件信息。128s表示文件名为128bytes长,l表示一个int或log文件类型,在此为文件大小
fileinfo_size = struct.calcsize('128sl')
# 定义文件头信息,包含文件名和文件大小
fhead = struct.pack('128sl', os.path.basename(filepath).encode('utf-8'), os.stat(filepath).st_size)
# 发送文件名称与文件大小
t.connecntsocket.send(fhead)
# 将传输文件以二进制的形式分多次上传至服务器
fp = open(filepath, 'rb')
while 1:
data = fp.read(1024)
if not data:
print ('{0} file send over...'.format(os.path.basename(filepath)))
break
t.connecntsocket.send(data)
def cancel(self):
self.txt_msgsend.delete('0.0', END) # 取消发送消息,即清空发送消息
'''绑定up键'''
def msgsendEvent(self,event):
if event.keysym == 'Up':
self.msgsend()
def run(self):
self.root.mainloop()
def my_close(self):
self.root.destroy()
my_removw(self.name)
def my_removw(name):
for c in Chat_list:
if c.name == name:
Chat_list.remove(c)
return