python實(shí)現(xiàn)同一局域網(wǎng)下傳輸圖片
簡(jiǎn)述
Python可以通過(guò)網(wǎng)絡(luò)套接字來(lái)進(jìn)行傳輸圖片 這點(diǎn)還是比較有意思的。
下面用TCP來(lái)進(jìn)行實(shí)現(xiàn),適用于Python3
代碼功能簡(jiǎn)述
下面代碼
實(shí)現(xiàn)了在一個(gè)電腦上發(fā)送圖片(Sender) 實(shí)現(xiàn)了在另外一個(gè)電腦(也可以是同一個(gè)電腦上的不同端口)接受圖片(Reciever) 只發(fā)一次,然后只收一次 新圖片會(huì)在舊圖片上多一個(gè) “new_”前綴 必須要先開(kāi)接受者代碼才行,之后再啟動(dòng)發(fā)送者代碼(不然發(fā)送者代碼會(huì)直接被拒絕) 下面是固定了在一個(gè)電腦上(看ip地址,下面寫(xiě)的是127.0.0.1,如果是其他電腦就寫(xiě)其他電腦上的ip地址) 另外本程序只能在同一個(gè)局域網(wǎng)下使用(就算是廣域網(wǎng)上,那就必須要使用廣域網(wǎng)的ip地址)代碼
【后附解析】
Sender.py (發(fā)送者)
import socketimport osimport sysimport structdef sock_client(): try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((’127.0.0.1’, 6666)) except socket.error as msg: print(msg) print(sys.exit(1)) while True: filepath = input(’input the file: ’) # 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(’client filepath: {0}’.format(filepath)) fp = open(filepath, ’rb’) while 1: data = fp.read(1024) if not data:print(’{0} file send over...’.format(filepath))break s.send(data) s.close() breakif __name__ == ’__main__’: sock_client()
Reciever.py (接受者)
import socketimport osimport sysimport structdef socket_service(): try: 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) except socket.error as msg: print(msg) sys.exit(1) print('Wait') while True: sock, addr = s.accept() deal_data(sock, addr) break s.close()def deal_data(sock, addr): print('Accept connection from {0}'.format(addr)) while True: fileinfo_size = struct.calcsize(’128sl’) buf = sock.recv(fileinfo_size) if buf: filename, filesize = struct.unpack(’128sl’, buf) fn = filename.decode().strip(’x00’) new_filename = os.path.join(’./’, ’new_’ + fn) recvd_size = 0 fp = open(new_filename, ’wb’) while not recvd_size == filesize:if filesize - 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()
解析:
發(fā)送者代碼:
還是先創(chuàng)建TCP套接字,并發(fā)起連接:
具體代碼如下:
try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((’127.0.0.1’, 6666)) except socket.error as msg: print(msg) print(sys.exit(1))
接下來(lái)的While循環(huán)中,就開(kāi)始進(jìn)行圖片發(fā)送
通過(guò)struct庫(kù)進(jìn)行打包,然后再用套接字來(lái)發(fā)送 注意:網(wǎng)絡(luò)上的有些代碼是不能直接用的,比如在這里,就需要把str變成bytes 通過(guò)os庫(kù)來(lái)獲取文件的基本名(這個(gè)是為了避免有些文件中包含具體路徑) 通過(guò)os庫(kù)來(lái)獲取文件的大小(通過(guò)文件狀態(tài)中關(guān)于大小的描述中獲取到)fhead = struct.pack(b’128sl’, bytes(os.path.basename(filepath), encoding=’utf-8’), os.stat(filepath).st_size)s.send(fhead)
之后再通過(guò)二進(jìn)制方式來(lái)獲取文件。 然后再發(fā)送出去,每次發(fā)送固定長(zhǎng)度的數(shù)據(jù)。先讀,再判斷是否為空,再發(fā)送。
接受端:
還是一樣,先創(chuàng)建套接字(不過(guò)這個(gè)需要綁定對(duì)應(yīng)的ip以及端口) 具體代碼如下:(這里寫(xiě)的是監(jiān)聽(tīng)10個(gè)套接字對(duì)象,但是在我們代碼中并沒(méi)喲用到)
try: 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) except socket.error as msg: print(msg) sys.exit(1)
之后就進(jìn)入到循環(huán),來(lái)判斷,是否獲取到sock對(duì)象,這里是會(huì)進(jìn)入阻塞狀態(tài)的。
在deal_data中就開(kāi)始通過(guò)連接的對(duì)象來(lái)獲取數(shù)據(jù)。
一樣,還是一個(gè)無(wú)限循環(huán),但其實(shí)本質(zhì)上還是空的。。。沒(méi)什么特別的。
之后就是對(duì)于傳過(guò)來(lái)的文件名處理一下,這里的這些“128sl”,其實(shí)就是一個(gè)大小規(guī)模(類似于打包的箱子大小的樣子)。然后就是得到新的文件名了。 對(duì)應(yīng)的代碼如下:
filename, filesize = struct.unpack(’128sl’, buf)fn = filename.decode().strip(’x00’)new_filename = os.path.join(’./’, ’new_’ + fn)
之后的recvd_size,其實(shí)就是為了來(lái)計(jì)數(shù)的標(biāo)簽 之后就不斷地收,邊收邊寫(xiě)入文件,一直到收完了之后。就關(guān)閉掉對(duì)應(yīng)的文件流 最后關(guān)閉套接字,退出循環(huán)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. Python 實(shí)現(xiàn)勞拉游戲的實(shí)例代碼(四連環(huán)、重力四子棋)2. python 寫(xiě)函數(shù)在一定條件下需要調(diào)用自身時(shí)的寫(xiě)法說(shuō)明3. Java GZip 基于內(nèi)存實(shí)現(xiàn)壓縮和解壓的方法4. jsp+servlet簡(jiǎn)單實(shí)現(xiàn)上傳文件功能(保存目錄改進(jìn))5. JavaScript數(shù)據(jù)結(jié)構(gòu)之雙向鏈表6. 利用CSS制作3D動(dòng)畫(huà)7. 一款功能強(qiáng)大的markdown編輯器tui.editor使用示例詳解8. 存儲(chǔ)于xml中需要的HTML轉(zhuǎn)義代碼9. SpringBoot+TestNG單元測(cè)試的實(shí)現(xiàn)10. .Net加密神器Eazfuscator.NET?2023.2?最新版使用教程
