from tkinter import *
from tkinter.filedialog import askopenfilename
import time
from threading import Thread
import socket
import sys
import os.path
import process
#聊天实现类
class ChatClient(Thread):
#构造函数
def __init__(self):
Thread.__init__(self)
#提示信息输出
self.__info_event=None
#读取数据输出
self.__out_event=None
#创建套接字
self.clientSock=socket.socket()
#重用地址
self.clientSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
#返回提醒信息
#info事件
@property
def info_event(self):
return self.__info_event
@info_event.setter
def info_event(self,handler):
self.__info_event=handler
#info输出
def info(self,content):
if self.info_event!=None:
self.info_event(content)
#返回接收结果
#out事件
@property
def out_event(self):
return self.__out_event
@out_event.setter
def out_event(self,handler):
self.__out_event=handler
#out输出
def out(self,content):
if self.out_event!=None:
self.out_event(content)
#发送信息
def send(self,content):
if self.clientSock==None:
self.info("已经断开连接")
return -1
if type(content) is str:
content=content.encode()
elif type(content) is bytes:
pass
else:
self.info("发送信息类型错误")
return -1
try:
self.clientSock.send(content)
#self.info("已经发送信息")
return 0
except:
self.info("丢失连接")
return -1
#接受信息
def recv(self):
recv_msg={}
if self.clientSock==None:
return
fileobj=self.clientSock.makefile("rb")
while True:
try:
line=fileobj.readline()
except:
return None
if not len(line):
return None
elif line==b"\r\n":
break
else:
#print(line)
key,value=line.decode().strip().split(": ")
recv_msg[key]=value
if "Length" in recv_msg:
length=int(recv_msg["Length"])
recv_msg["Content"]=b""
while length>0:
r=fileobj.read(min(1024,length))
length-=len(r)
recv_msg["Content"]+=r
fileobj.close()
elif "Count" in recv_msg:
count=int(recv_msg["Count"])
#print(count)
recv_msg["Content"]=b""
while count>0:
recv_msg["Content"]+=fileobj.readline()
count-=1
fileobj.close()
return recv_msg
def run(self):
while True:
recv_msg=self.recv()
if recv_msg==None:
break
self.out(recv_msg)
#连接chat服务器
def connserver(self,servername,serverport):
try:
self.clientSock.connect((servername,serverport))
#self.info("成功连接pchat服务器")
return 0
except BaseException as e:
self.info("连接pchat服务器失败")
return -1
#断开连接
def disconnserver(self):
if self.clientSock!=None:
self.clientSock.close()
self.clientSock=None
self.info("断开连接")
return 0
#主界面类
class MainWindow(Tk):
#构造函数
def __init__(self,name,pwd,chatwith=None):
Tk.__init__(self)
#用户名属性
self.username=name
self.password=pwd
self.chatwith=chatwith
self.init()
self.conn()
def conn(self,host="127.0.0.1",port=1234):
#初始化chatclient
self.chatclient=ChatClient()
#添加事件处理
self.chatclient.info_event=self.info
self.chatclient.out_event=self.out
#连接
r=self.chatclient.connserver(host,port)
#开始接收服务器发送的数据
self.chatclient.start()
return r
#属性用户名
@property
def username(self):
return self.__username
@username.setter
def username(self,name):
self.__username=name
@property
def password(self):
return self.__password
@password.setter
def password(self,pwd):
self.__password=pwd
#属性 聊天对象
@property
def chatwith(self):
return self.__chatwith
@chatwith.setter
def chatwith(self,name):
self.__chatwith=name
#初始化菜单
def init_menu(self):
menubar=Menu(self,bg="lightblue")
self["menu"]=menubar
sysmenu=Menu(menubar,bg="lightblue")
menubar.add_cascade(label="系统",menu=sysmenu)
#下拉菜单
sysmenu.add_command(label="配置",command=self.clientConfigure)
sysmenu.add_separator()
sysmenu.add_command(label="登陆",command=self.login)
sysmenu.add_command(label="注册",command=self.register)
sysmenu.add_command(label="注销",command=self.outlogin)
sysmenu.add_separator()
sysmenu.add_command(label="结束",command=self.destroy)
#设置标题
def setTitle(self,name):
self.title("【%s】PChat [%s]"%(self.username,name))
#界面初始化
def init(self):
self.setTitle(self.chatwith)
self.init_menu()
left_frame=Frame(self)
left_frame.pack(expand=YES,fill=BOTH,side=LEFT)
right_frame=Frame(self)
right_frame.pack(fill=Y,side=LEFT)
self.friends_list=Listbox(right_frame,bg="lightblue")
self.friends_list.pack(expand=YES,fill=BOTH)
self.friends_list.bind("<Double-Button-1>",self.select_friend)
self.friend_entry=Entry(right_frame)
self.friend_entry.pack(fill=X)
self.flush_button=Button(right_frame,text="刷新",command=self.flush)
self.flush_button.pack(side=LEFT)
self.add_button=Button(right_frame,text="增加",command=self.add)
self.add_button.pack(side=LEFT)
self.delete_button=Button(right_frame,text="删除",command=self.delete)
self.delete_button.pack(side=LEFT)
text_frame=Frame(left_frame,bg="white")
text_frame.pack(expand=YES,fill=BOTH)
self.chatmessage_text=Text(text_frame,bg="lightblue")
self.chatmessage_text.pack(expand=YES,fill=BOTH,side=LEFT)
text_scroll_bar=Scrollbar(text_frame,command=self.chatmessage_text.yview,bg="lightblue")
text_scroll_bar.pack(fill=Y,side=RIGHT)
self.chatmessage_text.configure(yscrollcommand=text_scroll_bar.set)
self.chatmessage_text.tag_config("header",foreground="green",font=("Arial",15))
self.chatmessage_text.tag_config("information",foreground="red",font=("Arial",10))
self.chatmessage_text.tag_config("file",foreground="yellow",font=("Arial",18))
self.chatmessage_text.tag_config("body",foreground="gray",font=("Arial",18))
self.inputmessage_string=StringVar()
self.inputmessage_entry=Entry(left_frame,bg="lightblue",textvariable=self.inputmessage_string)
self.inputmessage_entry.pack(fill=X)
self.inputmessage_entry.bind("<Return>",self.send)
self.send_button=Button(left_frame,text="发送",command=self.send,bg="lightblue")
self.send_button.pack(side=LEFT)
self.send_file_button=Button(left_frame,text="发送文件",command=self.sendfile)
self.send_file_button.pack(side=LEFT)
self.bottom_frame=Frame(self)
self.bottom_frame.pack(side=TOP,fill=X)
#self.usersname_label=Label(self.bottom_frame,text="用户名:")
#self.usersname_label.pack(side=LEFT)
#添加关闭窗口的事件处理
self.protocol("WM_DELETE_WINDOW",self.destroy)
def select_friend(self,event=None):
if len(event.widget.curselection()):
chatwith=event.widget.get(event.widget.curselection()[0])
if chatwith!="":
self.chatwith=chatwith
self.setTitle(self.chatwith)
#使用chatclietn发送数据
def __send(self,From,To,Date,Type,Length,content,Name=None):
if self.chatclient==None:
self.info("未连接服务器")
return -1
r=self.chatclient.send("From: "+From+"\r\n")
if r==-1:
return -1
r=self.chatclient.send("To: "+To+"\r\n")
if r==-1:
return -1
r=self.chatclient.send("Date: "+Date+"\r\n")
if r==-1:
return -1
r=self.chatclient.send("Type: "+Type+"\r\n")
if r==-1:
return -1
r=self.chatclient.send("Length: "+str(Length)+"\r\n")
if r==-1:
return -1
if Name!=None:
r=self.chatclient.send("Name: "+Name+"\r\n")
if r==-1:
return -1
r=self.chatclient.send("\r\n")
if r==-1:
return -1
r=self.chatclient.send(content)
if r==-1:
return -1
return 0
#刷新列表按钮事件处理
def flush(self,event=None):
cur_time=time.localtime()
text="".encode()
self.__send(self.username,"pchatsvr","%d:%d:%d"%(cur_time.tm_hour,cur_time.tm_min,cur_time.tm_sec),"List",len(text),text)
def add(self,event=None):
friend_name=self.friend_entry.get().strip()
if friend_name!="":
cur_time=time.localtime()
text=friend_name.encode()
self.__send(self.username,"pchatsvr","%d:%d:%d"%(cur_time.tm_hour,cur_time.tm_min,cur_time.tm_sec),"Add",len(text),text)
def delete(self,event=None):
friend_name=self.friend_entry.get().strip()
if friend_name!="":
cur_time=time.localtime()
text=friend_name.encode()
self.__send(self.username,"pchatsvr","%d:%d:%d"%(cur_time.tm_hour,cur_time.tm_min,cur_time.tm_sec),"Delete",len(text),text)
#发送信息按钮事件处理
def send(self,text=None):
if self.chatwith==None:
self.info("请选择聊天对象")
return
if self.inputmessage_string.get().strip()=="":
return
cur_time=time.localtime()
self.chatmessage_text.insert(END,"%s %d:%d:%d\n"%(self.username,cur_time.tm_hour,cur_time.tm_min,cur_time.tm_sec),"header")
self.chatmessage_text.insert(END,self.inputmessage_string.get()+"\n","body")
text=(self.inputmessage_string.get()).encode()
self.__send(self.username,self.chatwith,"%d:%d:%d"%(cur_time.tm_hour,cur_time.tm_min,cur_time.tm_sec),"Plain",len(text),text)
#发送文件按钮响应事件
def sendfile(self):
filename=askopenfilename()
if filename!="":
self.info("将发送文件:"+filename)
f=open(filename,"rb")
filecontent=f.read()
f.close()
cur_time=time.localtime()
self.__send(self.username,self.chatwith,"%d:%d:%d"%(cur_time.tm_hour,cur_time.tm_min,cur_time.tm_sec),"File",len(filecontent),filecontent,os.path.basename(filename))
else:
self.info("请选择文件")
#系统配置
def clientConfigure(self):
print("配置客户端")
#登陆
def login(self):
cur_time=time.localtime()
text=(self.username+"&"+self.password).encode()
self.__send(self.username,"pchatsvr","%d:%d:%d"%(cur_time.tm_hour,cur_time.tm_min,cur_time.tm_sec),"Login",len(text),text)
#注册
def register(self):
cur_time=time.localtime()
text=(self.username+"&"+self.password).encode()
self.__send(self.username,"pchatsvr","%d:%d:%d"%(cur_time.tm_hour,cur_time.tm_min,cur_time.tm_sec),"Register",len(text),text)
#注销
def outlogin(self):
cur_time=time.localtime()
text=("").encode()
self.__send(self.username,"pchatsvr","%d:%d:%d"%(cur_time.tm_hour,cur_time.tm_min,cur_time.tm_sec),"Outlogin",len(text),text)
#结束
def destroy(self):
cur_time=time.localtime()
text=("").encode()
r=self.__send(self.username,"pchatsvr","%d:%d:%d"%(cur_time.tm_hour,cur_time.tm_min,cur_time.tm_sec),"Quit",len(text),text)
if r==-1:
Tk.destroy(self)
#打开文件事件处理
def open(self,event):
#os.system("xdg-open %s"%("./recvfiles/"+event.widget["text"]))
process.system("/usr/bin/xdg-open %s"%("./recvfiles/"+event.widget["text"]))
#解析服务器响应
def parse(self,recv_msg):
if recv_msg["Type"]=="Plain":
self.chatmessage_text.insert(END,"%s %s\n"%(recv_msg["From"],recv_msg["Date"]),"header")
self.chatmessage_text.insert(END,recv_msg["Content"].decode()+"\n","body")
elif recv_msg["Type"]=="File":
#创建目录
try:
os.mkdir("./recvfiles")
except FileExistsError as e:
pass
f=open("./recvfiles/"+recv_msg["Name"],"wb")
f.write(recv_msg["Content"])
f.close()
filelabel=Label(self.chatmessage_text,fg="yellow",bg="lightblue",text=recv_msg["Name"],font=("宋体",15))
filelabel.bind("<Double-Button-1>",self.open)
self.chatmessage_text.insert(END,"%s %s\n"%(recv_msg["From"],recv_msg["Date"]),"header")
self.chatmessage_text.window_create(END,window=filelabel)
self.chatmessage_text.insert(END,"\n")
elif recv_msg["Type"]=="Status":
status_code=int(recv_msg["Content"].decode())
if status_code==100:
self.info("登陆成功")
elif status_code==101:
self.info("登陆失败:可能用户名或密码错误")
elif status_code==102:
self.info("没有登陆")
elif status_code==103:
self.info("已经存在登陆")
elif status_code==200:
self.info("注册成功")
elif status_code==201:
self.info("注册失败")
elif status_code==300:
self.info("发送成功")
elif status_code==301:
self.info(self.chatwith+"不在线")
elif status_code==302:
self.info("类型错误")
elif status_code==303:
self.info("没有文件名")
elif status_code==400:
self.info("注销成功")
elif status_code==500:
self.chatclient.disconnserver()
self.chatclient=None
elif status_code==600:
self.info("获取好友列表失败")
elif status_code==601:
self.info("增加好友成功")
elif status_code==602:
self.info("增加好友失败")
elif status_code==603:
self.info("删除好友成功")
elif status_code==604:
self.info("删除好友失败")
elif recv_msg["Type"]=="List":
#print("好友数目",recv_msg["Count"])
self.friends_list.delete(0,END)
for friend in recv_msg["Content"].decode().split("\r\n"):
#print("好友:",friend)
self.friends_list.insert(END,friend)
#chatclient info_event 事件处理函数
def info(self,text):
self.chatmessage_text.insert(END,text+"\n","information")
#chatclient out_event事件处理函数
def out(self,recv_msg):
if recv_msg!=None:
#显示接受数据在终端
#print(recv_msg)
self.parse(recv_msg)
if __name__=="__main__":
MainWindow(sys.argv[1],sys.argv[2]).mainloop()
#! /usr/bin/python3.4
'''
利用Tkinter,Socket,完成一个聊天软件开发
主要目的作为Tkinter学习的实战训练
自定义 chat 协议:
From: 来自 服务器名为pchatsvr
To: 目标
Date: 时间 eg(20:11:11)
Type: 发送内容类型:可选["Plain","File","Login","Outlogin","Register","Quit","Status","List","Add","Delete"]
Length: [可选]内容长度, 好友数目时将使用Count,不适用Length
Name:[可选]文件名
Count:[可选]好友数
//空行
...... 主体内容
状态码:
100 登陆成功
101 登陆失败
102 没有登陆
103 已经存在登陆
200 注册成功
201 注册失败
300 发送消息成功
301 To出错
302 Type出错
303 Name出错,当type为File时
400 注销成功
500 离开
600 例举好友失败
601 add好友成功
602 add好友失败
603 delete好友成功
604 delete好友失败
'''
import socket
import select
import time
import sqlite3
#chat服务类
class ChatServer():
def __init__(self):
self.servername="pchatsvr"
self.serverSock=socket.socket()
self.serverSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
self.usersdbname="users.db" #用户数据库
self.users={} #用户字典 只有登陆后才会添加 key用户名,value套接字
self.sockets=[] #套接字列表
self.init_db() #初始化数据库
def init_db(self):
self.conn=sqlite3.connect(database=self.usersdbname)
#用户表
try:
self.conn.execute("CREATE TABLE USERS(name VARCHAR(20) PRIMARY KEY,password VARCHAR(30) not null)")
except BaseException as e:
#print(e)
pass
#好友表
try:
self.conn.execute("CREATE TABLE FRIENDS(name_1 VARCHAR(20), name_2 VARCHAR(20),FOREIGN KEY(name_1) REFERENCES USERS(name),FOREIGN KEY(name_2) REFERENCES USERS(name))")
except BaseException as e:
#print(e)
pass
#关闭数据库
def close_db(self):
self.conn.close()
self.conn=None
#判断用户知否存在
def has_user_db(self,name,pwd):
try:
r=self.conn.execute("SELECT COUNT(*) FROM USERS WHERE name='%s' AND password='%s'"%(name,pwd))
for row in r:
if row[0]>0:
return True
else:
return False
except BaseException as e:
print(e)
def add_user_db(self,name,pwd):
if self.has_user_db(name,pwd):
return False
else:
try:
self.conn.execute("INSERT INTO USERS VALUES('%s','%s')"%(name,pwd))
self.conn.commit()
return True
except:
return False
def friends_list_db(self,name):
friends=[]
try:
res=self.conn.execute("SELECT name_2 FROM FRIENDS WHERE name_1='%s'"%(name))
for row in res:
friends.append(row[0])
return friends
except BaseException as e:
#print(e)
return None
#增加好友
def friend_add_db(self,name_1,name_2):
try:
self.conn.execute("INSERT INTO FRIENDS VALUES('%s','%s')"%(name_1,name_2))
self.conn.commit()
return True
except:
return False
#删除好友
def friend_delete_db(self,name_1,name_2):
try:
self.conn.execute("DELETE FROM FRIENDS WHERE name_1='%s' AND name_2='%s'"%(name_1,name_2))
return True
except:
return False
def start(self,hostname="",port=1234,listen_count=2):
self.serverSock.bind((hostname,port))
self.serverSock.listen(listen_count)
self.sockets.append(self.serverSock)
print("启动pchat服务监听")
self.__run()
def __select(self):
#作出响应
r_sockets=select.select(self.sockets,[],[])[0]
for sock in r_sockets:
#服务器套接字
if sock==self.serverSock:
newsock,addr=self.serverSock.accept()
print("accept:",addr)
self.sockets.append(newsock)
else:
recv_msg={}
fileobj=sock.makefile("rb",0)
while True:
try:
line=fileobj.readline()
except:
self.sockets.remove(sock)
sock.close()
return
if not len(line):
self.sockets.remove(sock)
sock.close()
return
if line==b"\r\n":
break
key,value=line.decode().strip().split(": ")
recv_msg[key]=value
length=int(recv_msg["Length"])
recv_msg["Content"]=b""
while length>0:
r=fileobj.read(min(length,1024))
if not len(r):
break
length-=len(r)
recv_msg["Content"]+=r
#print(recv_msg)
fileobj.close()
if recv_msg["Type"]=="Plain" or recv_msg["Type"]=="File":
if recv_msg["From"] not in self.users:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"102")
elif recv_msg["To"] not in self.users:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"301")
elif self.users[recv_msg["From"]]==sock:
if recv_msg["Type"]=="File" and "Name" not in recv_msg:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"303")
else:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"300")
#发送给聊天对象
chatwith_socket=self.users[recv_msg["To"]]
chatwith_socket.send(("From: "+recv_msg["From"]+"\r\n").encode())
chatwith_socket.send(("To: "+recv_msg["To"]+"\r\n").encode())
t=time.localtime()
chatwith_socket.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
chatwith_socket.send(("Type: "+recv_msg["Type"]+"\r\n").encode())
chatwith_socket.send(("Length: "+recv_msg["Length"]+"\r\n").encode())
if "Name" in recv_msg:
chatwith_socket.send(("Name: "+recv_msg["Name"]+"\r\n").encode())
chatwith_socket.send("\r\n".encode())
chatwith_socket.send(recv_msg["Content"])
else:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"103")
elif recv_msg["Type"]=="Login":
name,pwd=recv_msg["Content"].decode().split("&")
if self.has_user_db(name,pwd):
#将用户加入users中
if name not in self.users:
self.users[name]=sock
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"100")
else:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"103")
else:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"101")
elif recv_msg["Type"]=="Register":
name,pwd=name,pwd=recv_msg["Content"].decode().split("&")
if self.add_user_db(name,pwd):
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"200")
else:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"201")
elif recv_msg["Type"]=="Outlogin":
if recv_msg["From"] not in self.users:
#没有登陆
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"102")
elif self.users[recv_msg["From"]]==sock:
self.users.pop(recv_msg["From"])
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"400")
else:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"103")
elif recv_msg["Type"]=="Quit":
if recv_msg["From"] in self.users and self.users[recv_msg["From"]]==sock:
self.users.pop(recv_msg["From"])
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"500")
self.sockets.remove(sock)
sock.close()
elif recv_msg["Type"]=="List":
if not(recv_msg["From"] in self.users):
#没有登陆
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"102")
elif sock!=self.users[recv_msg["From"]]:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"103")
else:
friends=self.friends_list_db(recv_msg["From"])
if friends==None:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"600")
else:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: List\r\n".encode())
#sock.send("Length: \r\n".encode())
sock.send(("Count: "+str(len(friends))+"\r\n").encode())
sock.send("\r\n".encode())
for friend in friends:
sock.send((friend+"\r\n").encode())
elif recv_msg["Type"]=="Add":
if not (recv_msg["From"] in self.users):
#没有登陆
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"102")
elif sock!=self.users[recv_msg["From"]]:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"103")
else:
friend_name=recv_msg["Content"].decode()
if self.friend_add_db(recv_msg["From"],friend_name):
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"601")
else:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"602")
elif recv_msg["Type"]=="Delete":
if not(recv_msg["From"] in self.users):
#没有登陆
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"102")
elif sock!=self.users[recv_msg["From"]]:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"103")
else:
friend_name=recv_msg["Content"].decode()
if self.friend_delete_db(recv_msg["From"],friend_name):
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.sezhaond("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"603")
else:
sock.send(("From: "+self.servername+"\r\n").encode())
sock.send(("To: "+recv_msg["From"]+"\r\n").encode())
t=time.localtime()
sock.send(("Date: "+"%d:%d:%d"%(t.tm_hour,t.tm_min,t.tm_sec)+"\r\n").encode())
sock.send("Type: Status\r\n".encode())
sock.send("Length: 3\r\n".encode())
sock.send("\r\n".encode())
sock.send(b"604")
def __run(self):
while True:
try:
self.__select()
except KeyboardInterrupt as e:
self.close_db()
print("关闭pchat服务")
break
if __name__=="__main__":
ChatServer().start()
'''
自己实现popen和system,学习fork dup pipe exec 等等内容。
'''
import os
#采用双管道实现popen:dopen 这是HTTP中CGI的核心内容
def dopen(command):
f_read,s_write=os.pipe()
s_read,f_write=os.pipe()
spid=os.fork()
if spid<0:
return -1,-1
elif spid==0:
os.close(f_read)
os.close(f_write)
os.dup2(s_read,0)
os.dup2(s_write,1)
command_list=command.split(" ")
os.execv(command_list[0],command_list)
else:
os.close(s_read)
os.close(s_write)
return f_read,f_write
#模拟os.popen
def popen(command):
#创建管道
read_p,write_p=os.pipe()
spid=os.fork()
if spid<0:
return -1
elif spid==0:
#子进程
#关闭读端口
os.close(read_p)
os.dup2(write_p,1)
command_list=command.split(" ")
#替换子进程
os.execv(command_list[0],command_list)
else:
#父进程
os.close(write_p)
#返回管道读端
return read_p
#模拟os.system
def system(command):
spid=os.fork()
if spid<0:
return -1
elif spid==0:
command_list=command.split(" ")
os.execv(command_list[0],command_list)
else:
pass
if __name__=="__main__":
#dopen测试
r,w=dopen("/usr/bin/python3.4 test.py")
os.write(w,"hello world\n".encode())
while r>0:
content=os.read(r,1024)
if not len(content):
break
print(content.decode(),end="")
os.close(r)
#system测试#system("/usr/bin/xdg-open /home/qin/Documents/chat/chatclient.py")