服务端
实现目标
- GUI显示人机互动聊天内容,当客户端输入不完整内容,如’how old’,服务器能回复年龄等。
- GUI当客户端输入“send a file”,服务器端回复“please input the file name:”(在客户端显示)。
- (本文代码已实现)当客户端输入文件名后,服务器端如果有该文件,则发送该文件,否则回复客户端“This file does not exist”(此处博主建议采用异常处理)。客户端打印接收到的文件内容。
- 服务端发送程序参考如下:
if data == 'send a file':
data = conn.recv(1024).decode()
filename = data
file_size = os.path.getsize(filename)
fhead = struct.pack('l', file_size)
s.sendall(fhead)
fp = open(filename, 'rb')
while True:
data = fp.read(1024)
if not data:
break
s.sendall(data)
fp.close()
print("send over")
- (选)实现服务器与多客服通信功能。(线程实现)
- 多客服端参考代码如下:
import socket
from threading import Thread
from os.path import commonprefix
BUFSIZE=1024
def reply(conn):
while True:
data = conn.recv(1024).decode()
if not data:
break
print('Received message:', data)
m = 0
key = ''
for k in words.keys():
data = ' '.join(data.split())
if len(commonprefix([k, data])) > len(k)*0.7:
key = k
break
length = len(set(data.split())&set(k.split()))
if length > m:
m = length
key = k
conn.sendall(words.get(key, 'Sorry.').encode())
conn.close()
words = {'how are you?':'Fine,thank you.',
'how old are you?':'38',
'what is your name?':'Dong FuGuo',
"what's your name?":'Dong FuGuo',
'where do you work?':'University',
'bye':'Bye',
'send a file':'please input the file name:'}
HOST = '192.168.1.103'
PORT = 5007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(50)
print('Listening on port:',PORT)
while True:
conn, addr = s.accept()
print('Connected by', addr)
Thread(target=reply, args=(conn,)).start()
s.close()
聊天功能智能实现原理
commonprefix()函数
- os.path.commonprefix()是Python中的方法用于获取路径列表中最长的公共路径前缀。博主采用此函数来猜测对方要表达的真正意思。
实现代码
"""
Created on 2021-12-21 下午 07:47
@author: 浅笑醉红楼.([email protected])
@Software: PyCharm
(1) create by 浅笑醉红楼. 2021-12-21 下午 07:47
"""
import socket
from os.path import commonprefix
words={'how are you?':'Fine,thank you.',
'how old are you?':'38',
'what is your name?':'DongFuGuo',
"what's your name?":'DongFuGuo',
'where do you work?':'SDIBT',
'bye':'Bye',
'send a file':'please input the file name:'}
HOST=''
PORT=5007
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((HOST,PORT))
s.listen(1)
print('Listening at port:',PORT)
conn,addr=s.accept()
print('Connected by',addr)
while True:
data = conn.recv(1024).decode()
if not data:
break
print('Received message:', data)
m = 0
key = ''
for k in words.keys():
data = ' '.join(data.split())
if len(commonprefix([k, data])) > len(k)*0.7:
key = k
break
length = len(set(data.split())&set(k.split()))
if length > m:
m = length
key = k
conn.sendall(words.get(key, 'Sorry.').encode())
try:
if data == 'send a file':
data = conn.recv(1024).decode()
filename = data
file_size = os.path.getsize(filename)
fhead = struct.pack('l', file_size)
s.sendall(fhead)
fp = open(filename, 'rb')
while True:
data = fp.read(1024)
if not data:
break
s.sendall(data)
fp.close()
print("send over")
except Exception as e:
conn.sendall(words.get(data, 'This file does not exist').encode())
print("传输异常:", e)
conn.close()
s.close()
客服端
- GUI登录端代码见Python的GUI程序设计
- 实现代码如下:
"""
Created on 2021-12-22 上午 10:54
@author: 浅笑醉红楼.([email protected])
@Software: PyCharm
(1) create by 浅笑醉红楼. 2021-12-22 上午 10:54
"""
import wx
import socket
import sys
import struct
class ChatWND(wx.Frame):
def __init__(self, superior):
wx.Frame.__init__(self, parent=superior,title=u'Chat Window', size=(800, 600))
self.panel = wx.Panel(self, wx.ID_ANY)
self.panel.SetBackgroundColour("Green")
self.label1 = wx.StaticText(self.panel, -1, 'IP:', style=wx.ALIGN_LEFT)
self.label2 = wx.StaticText(self.panel, -1, 'PORT:', style=wx.ALIGN_RIGHT)
self.label3 = wx.StaticText(self.panel, -1, 'MSG:', style=wx.ALIGN_LEFT, size=(50, 50))
self.label4 = wx.StaticText(self.panel, -1, 'Send:', style=wx.ALIGN_LEFT, size=(50, 50))
self.textIP = wx.TextCtrl(self.panel, -1)
self.textPORT = wx.TextCtrl(self.panel, -1)
self.textRecord = wx.TextCtrl(self.panel, -1, style=wx.TE_MULTILINE, size=(520, 200))
self.textSend = wx.TextCtrl(self.panel, -1, style=wx.TE_MULTILINE, size=(520, 30))
self.buttonConnectSvr = wx.Button(self.panel, -1, 'Connect')
self.buttonSendMsg = wx.Button(self.panel, -1, 'Send')
self.buttonGetFiles = wx.Button(self.panel, -1, 'File')
sizer1 = wx.FlexGridSizer(2, 2, 20, 15)
sizer1.AddMany(
[
(self.label3, 0, wx.ALIGN_LEFT),
(self.textRecord, 0, wx.ALIGN_RIGHT),
(self.label4, 0, wx.ALIGN_LEFT),
(self.textSend, 0, wx.ALIGN_RIGHT),
])
sizer2 = wx.FlexGridSizer(1, 7, 5, 5)
sizer2.AddMany(
[(self.label1, 0, wx.ALIGN_LEFT),
(self.textIP, 0, wx.EXPAND),
(self.label2, 0, wx.ALIGN_LEFT),
(self.textPORT, 0, wx.ALIGN_RIGHT),
(self.buttonConnectSvr, 0, wx.EXPAND),
(self.buttonSendMsg, 0, wx.EXPAND),
(self.buttonGetFiles, 0, wx.ALIGN_RIGHT)
])
self.border = wx.BoxSizer(wx.VERTICAL)
self.border.Add(sizer1, 0, wx.ALL, 15)
self.border.Add(sizer2, 0, wx.ALL, 15)
self.panel.SetSizerAndFit(self.border)
self.Fit()
self.Bind(wx.EVT_BUTTON, self.OnButtonConnectSvr,self.buttonConnectSvr)
self.Bind(wx.EVT_BUTTON, self.OnButtonSendMsg,self.buttonSendMsg)
self.Bind(wx.EVT_BUTTON, self.OnButtonGetFiles,self.buttonGetFiles)
def ConnectSvr(self, HOST, PORT):
self.ClientSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
self.ClientSocket.connect((HOST, int(PORT)))
print('连接至服务器')
except socket.error:
print('Server not found or not open')
sys.exit()
def OnButtonConnectSvr(self, event):
HOST = self.textIP.GetValue()
PORT = self.textPORT.GetValue()
self.ConnectSvr(HOST, PORT)
def Chat(self):
strMsg = self.strSend
self.ClientSocket.sendall(strMsg.encode())
data = self.ClientSocket.recv(1024)
data = data.decode()
record = self.textRecord.GetValue() + 'Sever:' + data + '\n'
self.textRecord.SetValue(record)
if (strMsg.lower() == 'bye'):
self.ClientSocket.sendall(strMsg.encode())
data = self.ClientSocket.recv(1024)
record = self.textRecord.GetValue() + 'Sever:' + data + '\n'
self.textRecord.SetValue(record)
self.ClientSocket.close()
def OnButtonSendMsg(self, event):
self.strSend = self.textSend.GetValue()
record = self.textRecord.GetValue() + 'Me:' + self.strSend + '\n'
self.textRecord.SetValue(record)
self.textSend.SetValue('')
self.Chat()
def GetFiles(self):
filename = self.strSend
self.ClientSocket.sendall(filename.encode())
data = self.ClientSocket.recv(1024)
if (data.decode() == 'This file does not exist'):
record = self.textRecord.GetValue() + 'Sever:' + data.decode() + '\n'
self.textRecord.SetValue(record)
else:
data = self.ClientSocket.recv(1024)
f_info = struct.unpack('l', data)
file_size = f_info[0]
recv_size = 0
with open(filename[:filename.rfind('.')] + '_new' +
filename[filename.rfind('.'):], 'wb') as fp:
while not recv_size == file_size:
if file_size - recv_size > 1024:
data = self.ClientSocket.recv(1024)
recv_size += len(data)
else:
data = self.ClientSocket.recv(file_size - recv_size)
recv_size = file_size
fp.write(data)
record = self.textRecord.GetValue() + 'Received a file' + '\n'
self.textRecord.SetValue(record)
def OnButtonGetFiles(self, event):
self.strSend = self.textSend.GetValue()
record = self.textRecord.GetValue() + 'Me:' + self.strSend + '\n'
self.textRecord.SetValue(record)
self.textSend.SetValue('')
self.GetFiles()
if __name__ == '__main__':
app=wx.App()
frame = ChatWND(None)
frame.Show()
app.MainLoop()
