Python可以通过网络sockets来传输图片,还是挺有意思的。下面是用TCP实现的,适用于Python3。代码功能简述在一台电脑上实现发送图片(Sender)在另一台电脑上实现接收图片(或者同一台电脑的不同端口)(Reciever)只发送一次,然后只接收一次新图片会在一张老图上多了“new_”前缀一定要先开启receiver代码,再启动sender代码(否则sender代码会直接被拒绝)下面固定在一台电脑上(看ip地址,下面写的是127.0.0.1,如果是另一台电脑,就写另一台电脑的ip地址)另外,本程序只能在同一个局域网下使用(即使是广域网,也必须使用广域网的ip地址)代码Sender.py(发件人):importsocketimportosimportsysimportstructdefsock_client():try:s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.connect(('127.0.0.1',6666))除了套接字。错误为msg:print(msg)print(sys.exit(1))whileTrue:filepath=input('inputthefile:')#filepath='test.png'fhead=struct.pack(b'128sl',bytes(os.path.basename(filepath),encoding='utf-8'),os.stat(filepath).st_size)s.send(fhead)print('clientfilepath:{0}'.format(filepath))fp=open(filepath,'rb')while1:data=fp.read(1024)ifnotdata:print('{0}filesendover...'.format(文件路径))breaks.send(data)s.close()breakif__name__=='__main__':sock_client()Reciever.py(receiver):importsocketimportosimportsysimportstructdefsocket_s服务():尝试:s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)s.bind(('127.0.0.1',6666))s。listen(10)除了socket.errorasmsg:print(msg)sys.exit(1)print("Wait")whileTrue:sock,addr=s.accept()deal_data(sock,addr)breaks.close()defdeal_data(sock,addr):print("Acceptconnectionfrom{0}".format(addr))whileTrue:fileinfo_size=struct.calcsize('128sl')buf=sock.recv(fileinfo_size)ifbuf:filename,filesize=struct.unpack('128sl',buf)fn=filename.decode().strip('\x00')new_filename=os.path.join('./','new_'+fn)recvd_size=0fp=open(new_filename,'wb')而不是recvd_size==filesize:iffilesize-recvd_size>1024:data=sock.recv(1024)recvd_size+=len(data)else:data=sock.recv(1024)recvd_size=filesizefp.write(data)fp.close()sock.close()breakif__name__=='__main__':socket_service()解析发送者代码:先创建TCP套接字,并发起连接具体代码如下:try:s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.connect(('127.0.0.1',6666))exceptsocket.errorasmsg:print(msg)print(sys.exit(1))在接下来的While循环中,开始发送图片。通过struct库封装,然后使用socket发送注意:网上有些代码不能直接使用。比如这里需要将str换成bytes通过os库获取文件的基本名称(这是为了避免某些文件包含特定路径)使用os库获取文件的大小(从文件状态中的大小描述中获得)fhead=struct.pack(b'128sl',bytes(os.path.basename(filepath),encoding='utf-8'),os.stat(filepath)。st_size)s.send(fhead)然后以二进制方式获取文件。然后发送出去,每次发送固定长度的数据。先读取,再判断是否为空,再发送。接收端:还是一样,先创建一个socket(不过这个需要绑定对应的ip和端口)具体代码如下:(这里写的是监听10个socket对象,但是在我们中并没有用到代码)尝试:s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)s.bind(('127.0.0.1',6666))s.listen(10)exceptsocket.errorasmsg:print(msg)sys.exit(1)后进入循环判断sock对象是否已经获取,这里会进入阻塞状态。在deal_data中,开始通过连接对象获取数据。同样,它仍然是一个无限循环,但它本质上仍然是空的,没有什么特别的。之后,我们需要对传入的文件名进行处理,这里的这些“128sl”其实就是一个尺寸(类似于一个包装盒的尺寸)。然后只需获取新文件名即可。对应代码如下:filename,filesize=struct.unpack('128sl',buf)fn=filename.decode().strip('\x00')new_filename=os.path.join('./','new_'+fn)后的recvd_size其实就是一个计数的标签。之后就一直在收集,边收集边写文件,直到收集结束。关闭相应的文件流。最后关闭套接字并退出循环。
