1.项目意义
1、了解网络的结构;
2、了解网络传输协议;
3、掌握基本的网络编程方法。
2.总体设计
使用 TCP 协议实现人机聊天互动,程序具有服务端和客户端:
(1)必备功能:要求服务端代码具有一定的智能,能够根据不完整的问题识别客户端真正 要问的问题。如客户输入how old, 服务器能回答年龄。
(2)必备功能:服务器客户端之间能简单发送和接收文件。至少应有序列化和反序列化功 能。收发双方,应打印显示发送或接收的原始对象的信息(非字节串)。
3.程序描述
1、TCP客户端:
(1)发送信息的函数
def SendMessage():
mySocket.sendall("111-111".encode())
sendLines = SendInput.get("0.0", END)
mySocket.sendall(sendLines.encode())
ShowInput.insert(END,"\t\t\t"+sendLines[:-1]+" :(Client)\n")
ShowInput.insert(END,"(Server):"+mySocket.recv(BUFSIZE).decode()+"\n")
SendInput.delete("0.0", END)
(2)发送文件的函数
def SendFile():
mySocket.sendall("222-222".encode())
filename = askopenfilename()
#ShowInput.insert(END, filename+ s +" SendFile \n")
#建立socket
file_size=os.path.getsize(filename)
fhead = struct.pack('l',file_size)
mySocket.sendall(fhead)
fp=open(filename,'rb')
while True:
data=fp.read(BUFSIZE)
if not data:
break
mySocket.sendall(data)
fp.close()
ShowInput.insert(END, "filename: "+filename+" :(Client)\n")
ShowInput.insert(END, "\t\t\t\tsend over"+" :(Client)\n")
(3)界面部分
frame = Frame(RootWindow, bg = 'Tan',)
frame1 = Frame(RootWindow, bg = 'Tan',)
ShowInput = Text(RootWindow, width = 200,
height = 7,
bg = 'Tan',
fg = 'linen',
font = ('微软雅黑',10))
SendInput = Text(RootWindow, width = 200,
height = 4,
bg = 'Tan',
fg = 'linen',
font = ('微软雅黑',10))
MessageLabel = Label(frame, text = "收发信息框:",
bg = 'Tan',
fg = 'linen',
font = ('微软雅黑',8))
InputLabel = Label(frame1, text = "输入框:",
bg = 'Tan',
fg = 'linen',
font = ('微软雅黑',8))
blankLabel = Label(RootWindow)
ChatBtn = Button(RootWindow, text = "聊天",
width = 7,
relief = RIDGE,
bg = 'Tan',
fg = 'linen',
font = ('微软雅黑',11),
command = SendMessage)
FielBtn = Button(RootWindow, text = "发送文件",
width = 7,
relief = RIDGE,
bg = 'Tan',
fg = 'linen',
font = ('微软雅黑',11),
command = SendFile)
menubtn = Menubutton(RootWindow,text = '快速对话',
width = 7,
relief = RIDGE,
bg = 'Tan',
fg = 'linen',
font = ('微软雅黑',11))
menu = Menu(menubtn, tearoff = True)
for word in words:
menu.add_radiobutton(label = word, command = lambda word_name = word : InsertLines(word_name))
menubtn.config(menu = menu)
(4)界面布局部分
frame.pack(side = 'top', padx = 10, pady = 0,fill = BOTH)
MessageLabel.pack(side = 'left', padx = 0, pady = 0)
ShowInput.pack(side = 'top', padx = 10, pady = 0)
blankLabel.pack(side = 'top', padx = 10, pady = 0)
frame1.pack(side = 'top', padx = 10, pady = 0,fill = BOTH)
InputLabel.pack(side = 'left', padx = 0, pady = 0)
SendInput.pack(side = 'top', padx = 10, pady = 0)
ChatBtn.pack(side = 'right', padx = 10, pady = 6)
FielBtn.pack(side = 'right', padx = 10, pady = 6)
menubtn.pack(side = 'right', padx = 10, pady = 6)
2、TCP服务端
(1)接收信息
if data == "111-111":
#处理分析发送函数请求
print("receive message!")
messageFalg = True
if messageFalg:
if data != "111-111":
print('Received message:', data[0:-1])
#字符匹配
mydata = ''
for item in words.keys():
if item.find(data[0:-1]) != -1:
mydata = item
break
conn.sendall(words.get(mydata,"Sorry, I dont' know!").encode())
messageFalg = False
(2)接收文件
if data == "222-222":
print("receive file!")
fileFlag = True
if fileFlag:
data = conn.recv(BUFSIZE)
f_info=struct.unpack('l',data)
file_size=f_info[0]
recv_size=0
while not recv_size==file_size:
with open('ClientFile_'+str(filenuber)+'.dat','ab') as fp:
if file_size - recv_size > BUFSIZE:
data = conn.recv(BUFSIZE)
recv_size += len(data)
else:
data= conn.recv(file_size - recv_size)
recv_size = file_size
print(data)
fp.write(data)
filenuber = filenuber + 1
print('received a file :' + 'ClientFile'+str(filenuber)+'.dat')
fileFlag = False
4 测试要点
(1)测试TCP连接是否成功
(2)试接收信息是否完整
(3)测试智能回复聊天
(4)测试其他无关键词汇
(5)测试文件发送与接收