在开发一些需要网络通信的应用中,经常会用到各种网络协议进行通信,博主在开发实验室的机器人的时候就遇到了需要把机器人上采集到的图片传回服务器进行处理识别,在python下的实现方式如下(只贴出了关键代码)
服务器端
LOCAL_IP='192.168.100.22'#本机在局域网中的地址,或者写127.0.0.1
PORT=2567#指定一个端口defserver():
sock= socket.socket(socket.AF_INET, socket.SOCK_STREAM)# socket.AF_INET 指ipv4 socket.SOCK_STREAM 使用tcp协议
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)#设置端口
sock.bind((LOCAL_IP, PORT))#绑定端口
sock.listen(3)#监听端口whileTrue:
sc,sc_name= sock.accept()#当有请求到指定端口是 accpte()会返回一个新的socket和对方主机的(ip,port)print('收到{}请求'.format(sc_name))
infor= sc.recv(1024)#首先接收一段数据,这段数据包含文件的长度和文件的名字,使用|分隔,具体规则可以在客户端自己指定
length,file_name= infor.decode().split('|')if lengthand file_name:
newfile=open('image/'+str(random.randint(1,10000))+'.jpg','wb')#这里可以使用从客户端解析出来的文件名print('length {},filename {}'.format(length,file_name))
sc.send(b'ok')#表示收到文件长度和文件名file= b''
total=int(length)
get=0while get< total:#接收文件
data= sc.recv(1024)file+= data
get= get+len(data)print('应该接收{},实际接收{}'.format(length,len(file)))iffile:print('acturally length:{}'.format(len(file)))
newfile.write(file[:])
newfile.close()
sc.send(b'copy')#告诉完整的收到文件了
sc.close()
客户端
address=('192.168.100.22',2567)defsend(photos):for photoin photos[0]:print('sending {}'.format(photo))
data= file_deal(photo)
sock= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(address)
sock.send('{}|{}'.format(len(data),file).encode())#默认编码 utf-8,发送文件长度和文件名
reply= sock.recv(1024)if'ok'== reply.decode():#确认一下服务器get到文件长度和文件名数据
go=0
total=len(data)while go< total:#发送文件
data_to_send= data[go:go+1024]
sock.send(data_to_send)
go+=len(data_to_send)
reply= sock.recv(1024)if'copy'== reply.decode():print('{} send successfully'.format(photo))
sock.close()#由于tcp是以流的形式传输数据,我们无法判断开头和结尾,简单的方法是没传送一个文件,就使用一个socket,但是这样是消耗计算机的资源,博主正在探索更好的方法,有机会交流一下deffile_deal(file_path):#读取文件的方法
mes= b''try:file=open(file_path,'rb')
mes=file.read()except:print('error{}'.format(file_path))else:file.close()return mes