[英]python socket programming for transferring a photo
我是python套接字編程的新手。 這是在Mininet主機中打開TCP套接字並將照片從一台主機發送到另一台主機的示例。 實際上,為了滿足我的要求,我更改了用於向另一台主機發送簡單消息( 將接收到的數據寫入文本文件 )的代碼。 盡管當我實現此修訂的代碼時,沒有錯誤,並且似乎可以正確傳輸,但是我不確定這是否是進行此傳輸的正確方法。 由於我在同一台計算機上運行兩個主機,因此我認為這可能會對結果產生影響。 我想請您檢查這是否是正確的轉移方式,還是應該添加或刪除某些內容。
mininetSocketTest.py#!/ usr / bin / python
from mininet.topo import Topo, SingleSwitchTopo
from mininet.net import Mininet
from mininet.log import lg, info
from mininet.cli import CLI
def main():
lg.setLogLevel('info')
net = Mininet(SingleSwitchTopo(k=2))
net.start()
h1 = net.get('h1')
p1 = h1.popen('python myClient2.py')
h2 = net.get('h2')
h2.cmd('python myServer2.py')
CLI( net )
#p1.terminate()
net.stop()
if __name__ == '__main__':
main()
myServer2.py
import socket
import sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('10.0.0.1', 12345))
buf = 1024
f = open("2.jpg",'wb')
s.listen(1)
conn , addr = s.accept()
while 1:
data = conn.recv(buf)
print(data[:10])
#print "PACKAGE RECEIVED..."
f.write(data)
if not data: break
#conn.send(data)
conn.close()
s.close()
myClient2.py:
import socket
import sys
f=open ("1.jpg", "rb")
print sys.getsizeof(f)
buf = 1024
data = f.read(buf)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('10.0.0.1',12345))
while (data):
if(s.sendall(data)):
#print "sending ..."
data = f.read(buf)
print(f.tell(), data[:10])
else:
s.close()
s.close()
client2
此循環是錯誤的:
while (data):
if(s.send(data)):
print "sending ..."
data = f.read(buf)
正如send
文檔所說:
返回發送的字節數。 應用程序負責檢查所有數據是否已發送; 如果僅傳輸了一些數據,則應用程序需要嘗試傳送其余數據。 有關此主題的更多信息,請參考Socket Programming HOWTO 。
您甚至都沒有嘗試這樣做。 因此,盡管它可能可以在localhost上運行,但在輕載的機器上且文件很小,但是一旦您嘗試將其真正使用,它就會崩潰。
正如幫助所述,您需要做一些事情來交付其余的緩沖區。 由於可能沒有充分的理由,您不能僅在全部發送sendall
,因此最簡單的方法是調用sendall
:
與send()不同,此方法繼續從字節發送數據,直到所有數據都已發送或發生錯誤為止。 成功不返回任何內容。 如果出錯,則會引發異常…
這帶來了下一個問題:您不在任何地方進行任何異常處理。 也許還可以,但通常不行。 例如,如果您的一個套接字發生故障,而另一個套接字仍然發生故障,您是否要中止整個程序並硬斷開連接,還是想先完成所有發送的操作?
您至少應該使用一個finally
的with
子句,以確保您干凈地close
套接字,以便另一端會得到一個不錯的EOF而不是異常。
另外,您的服務器代碼僅服務於一個客戶端,然后退出。 那真的是您想要的嗎? 通常,即使您不需要並發客戶端,您至少也要一遍一遍地接受和服務它們。
最后,服務器幾乎總是想這樣做:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
如果不這樣做,如果您嘗試在服務器完成后幾秒鍾內再次運行服務器(特定於平台的秒數,甚至可能取決於它是否以異常而不是完全關閉而完成),則bind
將失敗,就像您試圖綁定另一個程序實際上正在使用的套接字一樣。
首先,您應該使用TCP而不是UDP。 TCP將確保您的客戶端/服務器正確接收了整個照片。 UDP更用於內容流。 絕對不是您的用例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.