1 Star 4 Fork 0

蓝色小镇 / python 聊天室

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
server.pyw 12.70 KB
一键复制 编辑 Web IDE 原始数据 按行查看 历史
蓝色小镇 提交于 2018-06-17 19:19 . Upload server.pyw client.pyw
'''
chat room client
autor by chenkai
finished time 2018/6/14
'''
import socket
import select
import threading
import os
import hashlib
import tkinter as tk
from tkinter import *
from tkinter import scrolledtext
import tkinter.messagebox
import time
import pymysql
##服务器
class App(tk.Tk):
def __init__(self):
super().__init__()
self.ip=StringVar()
self.port=StringVar()
self.clients={}
self.inputs=[]
self.outputs=[]
self.s=None
self.tkgui()
def tkgui(self):
self.title('服务端')
self.geometry('600x600')
self.l_ip=tk.Label(self,text='服务器ip:')
self.l_ip.grid(row=0,column=0,padx=10,pady=10,sticky=tk.E)
self.e_ip=tk.Entry(self,textvariable=self.ip)
self.e_ip.grid(row=0,column=1,padx=10,pady=10,sticky=tk.W)
self.ip.set('127.0.0.1')
self.l_port=tk.Label(self,text='服务器端口:')
self.l_port.grid(row=1,column=0,padx=10,pady=10,sticky=tk.E)
self.e_port=tk.Entry(self,textvariable=self.port)
self.e_port.grid(row=1,column=1,padx=10,pady=10,sticky=tk.W)
self.port.set('12306')
self.btnst=tk.Button(self,text='开启服务',command=self.cthread)
self.btnst.grid(row=2,column=0,padx=5,pady=5,sticky=tk.E)
self.btnsp=tk.Button(self,text='断开服务',command=self.stopServer)
self.btnsp.grid(row=2,column=1,padx=5,pady=5,sticky=tk.W)
self.btnsp.configure(state='disable')
self.sW=80
self.sH=30
self.scr=scrolledtext.ScrolledText(self,width=self.sW,height=self.sH,wrap=tk.WORD)
self.scr.grid(row=5,column=0,columnspan=2)
def makelog(self,str_):
conn = pymysql.connect(host='localhost', user='root', password='root', db='uesr_log', charset='utf8')
sql = 'insert into msglog (msg,time) values (%s,%s)'
cus1 = conn.cursor()
cus1.execute(sql, (str_, time.ctime()))
print('log success\n')
conn.close()
def mk_file_log(self,str_):
f = open('./log.txt', 'a', encoding='UTF-8', errors='ignore')
# f.readlines()
f.write(time.ctime() + ' 登陆信息:' + str_ + ' ' + "\n")
f.close()
def tcpserve(self):
## if not os.path.exists('d:/chat/'):
## os.makedirs('d:/chat/')
while True:
try:
stdinput, stdoutput, stderr = select.select(self.inputs, self.outputs, self.inputs)
except:
#print('断开')
self.clients.clear()
return
for obj in stdinput:
if obj is self.s:
try:
c,addr=self.s.accept()
except:
#print('断开')
return
self.inputs.append(c)
self.clients[addr]=c
for l in self.clients:
try:
self.clients[l].sendall((time.ctime()+'{}已登入').format(str(addr)).encode('utf-8'))
except:
pass
#print('{}已登入'.format(str(addr)))
str_time=time.ctime()
self.scr.insert("insert",str_time.format(str(addr))+"\n")
self.scr.insert("insert",'{}已登入\n'.format(str(addr)))
self.mk_file_log('{}已登入\n'.format(str(addr)))
self.scr.see(tk.END)
self.scr.update()
else:
try:
acceptmsg=str(obj.recv(1024),encoding='utf-8')
#print(''.join([acceptmsg,' 客户端口:',str(addr[1])]))
#if acceptmsg !="" :
# tts=threading.Thread(target=self.receiv,args=(acceptmsg,))
# tts.start()
if acceptmsg !="" :
ts = threading.Thread(target=self.makelog,args=(acceptmsg,))
# ts.setDaemon(True)
ts.start()
#accptdata=''.join([' 客户端口:',str(addr[1]),":",acceptmsg])
accptdata=''.join([acceptmsg])
accptdata=accptdata+'\n'
for k in self.clients:
self.clients[k].sendall(accptdata.encode('utf-8'))
self.scr.insert("insert",accptdata)
self.scr.see(tk.END)
self.scr.update()
if obj not in self.outputs:
self.outputs.append(obj)
except ConnectionResetError:
adr=obj.getpeername()
self.clients={k:v for k,v in self.clients.items() if k!=adr }
for b in self.clients:
#try:
self.clients[b].sendall('{}已退出'.format(str(adr)).encode('utf-8'))
#print('{}已退出'.format(str(adr)))s
self.mk_file_log('{}已退出\n'.format(str(adr)))
self.scr.insert("insert",'{}已退出\n'.format(str(adr)))
self.scr.see(tk.END)
self.scr.update()
#except:
##print('err')
if not self.clients:
#print('最后一位{}已退出'.format(str(adr)))
self.scr.insert("insert",'最后一位:{}已退出\n'.format(str(adr)))
self.scr.see(tk.END)
self.scr.update()
self.inputs.remove(obj)
## with open('d:/chat/c.txt','r') as f:
## accptall=f.read()
## sendmsg=accptall
## c.sendall(sendmsg.encode('utf-8'))
## c.close()
def main(self):
self.s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
## host='127.0.0.1'
## port=8800
self.host=self.ip.get()
self.e_port=self.port.get()
if not self.host:
tkinter.messagebox.showinfo('提示','请输入IP地址!')
self.scr.insert("insert",'开启失败\n')
self.scr.see(tk.END)
self.scr.update()
return
if not self.e_port:
tkinter.messagebox.showinfo('提示','请输入端口!')
self.scr.insert("insert",'开启失败\n')
self.scr.see(tk.END)
self.scr.update()
return
try:
self.e_port=int(self.e_port)
except:
#print('无效端口!')
tkinter.messagebox.showinfo('提示','无效端口!')
self.scr.insert("insert",'开启失败\n')
self.scr.see(tk.END)
self.scr.update()
return
##s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1024)
try:
self.s.bind((self.host,self.e_port))
except:
#print('开启失败')
self.scr.insert("insert",'开启失败\n')
self.scr.see(tk.END)
self.scr.update()
tkinter.messagebox.showinfo('提示','开启失败,IP或端口错误!')
return
self.s.listen(15)
self.inputs = [self.s]
self.btnst.configure(state='disable')
self.btnsp.configure(state='normal')
self.tcpserve()
def cthread(self):
t=threading.Thread(target=self.main)
t.start()
tse=threading.Thread(target=self.file_save)
tse.start()
#t.join()
#print('已开启')
self.scr.insert("insert",'已开启\n')
self.scr.see(tk.END)
self.scr.update()
def stopServer(self):
self.scr.insert("insert",'已断开\n')
self.scr.see(tk.END)
self.scr.update()
#print('已断开')
self.s.close()
self.clients.clear()
self.inputs.clear()
self.outputs.clear()
self.btnst.configure(state='normal')
self.btnsp.configure(state='disable')
def file_op(self,str_):
client = socket.socket() # 生成socket连接对象
ip_port = ("localhost", 6970) # 地址和端口号
client.connect(ip_port) # 连接
print("服务器已连接")
content = str_
if len(content) == 0: return # 如果传入空字符会阻塞
if content.startswith("get"):
client.send(content.encode("utf-8")) # 传送和接收都是bytes类型
# 1.先接收长度,建议8192
server_response = client.recv(1024)
file_size = int(server_response.decode("utf-8"))
print("接收到的大小:", file_size)
# 2.接收文件内容
client.send("准备好接收".encode("utf-8")) # 接收确认
sp=content.split("/")
filename = "下载/" + sp[len(sp)-1]
f = open(filename, "wb")
received_size = 0
m = hashlib.md5()
while received_size < file_size:
size = 0 # 准确接收数据大小,解决粘包
if file_size - received_size > 1024: # 多次接收
size = 1024
else: # 最后一次接收完毕
size = file_size - received_size
data = client.recv(size) # 多次接收内容,接收大数据
data_len = len(data)
received_size += data_len
print("已接收:", int(received_size / file_size * 100), "%")
m.update(data)
f.write(data)
f.close()
print("实际接收的大小:", received_size) # 解码
# 3.md5值校验
md5_sever = client.recv(1024).decode("utf-8")
md5_client = m.hexdigest()
print("服务器发来的md5:", md5_sever)
print("接收文件的md5:", md5_client)
if md5_sever == md5_client:
print("MD5值校验成功")
else:
print("MD5值校验失败")
client.close()
return
def file_save(self):
server = socket.socket()
server.bind(("localhost", 6980)) # 绑定监听端口
server.listen(5) # 监听
print("监听开始..")
while True:
conn, addr = server.accept() # 等待连接
print("conn:", conn, "\naddr:", addr) # conn连接实例
while True:
data = conn.recv(1024) # 接收
if not data: # 客户端已断开
print("客户端断开连接")
break
print("收到的命令:", data.decode("utf-8"))
sp=data.decode("utf-8").split(" ")
cmd = sp[0]
filename=sp[1]
ts = threading.Thread(target=self.mk_file_log, args=(data,))
# ts.setDaemon(True)
ts.start()
if cmd == "get":
if os.path.isfile(filename): # 判断文件存在
# 1.先发送文件大小,让客户端准备接收
size = os.stat(filename).st_size # 获取文件大小
conn.send(str(size).encode("utf-8")) # 发送数据长度
print("发送的大小:", size)
# 2.发送文件内容
conn.recv(1024) # 接收确认
m = hashlib.md5()
f = open(filename, "rb")
for line in f:
conn.send(line) # 发送数据
m.update(line)
f.close()
# 3.发送md5值进行校验
md5 = m.hexdigest()
conn.send(md5.encode("utf-8")) # 发送md5值
print("md5:", md5)
elif cmd == "send":
#ts = threading.Thread(target=self.file_op,args=("get "+filename,))
#ts.start()
self.file_op("get "+filename)
server.close()
if __name__=='__main__':
app=App()
app.mainloop()
Python
1
https://gitee.com/ck_king/python_chat_room.git
git@gitee.com:ck_king/python_chat_room.git
ck_king
python_chat_room
python 聊天室
master

搜索帮助

14c37bed 8189591 565d56ea 8189591