問題
你要通過網路連線程式設計客棧傳送和接受連續資料的大型xswfybaafh陣列,並儘量減少資料的複製操作。
解決方案
下面的函式利用 memoryviews 來傳送和接受大陣列:
# zerocopy.py
def send_from程式設計客棧(arr, dest):
v程式設計客棧iew = memoryview(arr).cast('b')
while len(view):
nsent = dest.send(view)
view = view[nsent:]
def recv_into(arr, source):
view = memoryview(arr).cast('b')
while len(view):
nrecv = source.recv_into(view)
view = view[nrecv:]
為了測試程式,首先建立乙個通過socket連線的伺服器和客戶端程式:
>>> from socket import *
>>> s = socket(af_inet, sock_stream)
>>> s.bind(('', 25000))
>>> s.listen(1)
>>> c,a = s.accept()
>>>
在客戶端(另外乙個直譯器中):
>>> from socket import *
>>> c = socket(af_inet, sock_stream)
>>> c.connect(('localhost', 25000))
>>>
本節的目標是你能通過連線傳輸乙個超大陣列。這種情況的話,可以通過 array 模組或 numpy 模組來建立陣列:
# server
>>> import numpy
>>> a = numpy.arange(0.0, 50000000.0)
>>> send_from(a, c)
>>>
# client
>>> import numpy
>>> a = numpy.zeros(shape=50000000, dtype=float)
>>> a[0:10]
array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
>>> recv_into(a, c)
>>> a[0:10]
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
>>>
討論在資料密集型分布式計算和平行計算程式中,自己寫程式來實現傳送/接受大量資料並不常見。 不過,要是你確實想這樣做,你可能需要將你的資料轉換成原始位元組,以便給低層的網路函式使用。 你可能還需要將資料切割成多個塊,因為大部分和網路相關的函式並不能一次性傳送或接受超大資料塊。
一種方法是使用某種機制序列化資料——可能將其轉換成乙個位元組字串。 不過,這樣最終會建立資料的乙個複製。 就算你只是零碎的做這些,你的**最終還是會有大量的小型複製操作。
本節通過使用記憶體檢視展示了一些魔法操作。 本質上,乙個記憶體檢視就是乙個已存在陣列的覆蓋層。不僅僅是那樣, 記憶體檢視還能以不同的方式轉換成不同型別來表現資料。 這個就是下面這個語句的目的:
view = memoryview(arr).cast('')
它接受乙個陣列 arr並將其轉換為乙個無符號位元組的記憶體檢視。這個檢視能被傳遞給socket相關函式, 比如socket.send()或send.recv_into()。 在內部,這些方法能夠直接操作這個記憶體區域。例如,sock.send()直接從記憶體中發生資料而不需要複製。send.recv_into()使用這個記憶體區域作為接受操作的輸入緩衝區。
剩下的乙個難點就是socket函式可能只操作部分資料。 通常來講,我們得使用很多不同的send()和recv_into()來傳輸整個陣列。 不用擔心,每次操作後,檢視會通過傳送或接受位元組數量被切割成新的檢視。 新的檢視同樣也是記憶體覆蓋層。因此,還是沒有任何的複製操作。
這裡有個問題就是接受者必須事先知道有多少資料要被傳送, 以便它能預分配乙個陣列或者確保它能將接受的資料放入乙個已經存在的陣列中。 如果沒辦法知道的話,傳送者就得先將資料大小傳送過來,然後再傳送實際的陣列資料。
Python利用socket傳送與接收檔案001
應用場景 語言python,利用socket進行檔案傳輸 針對windows本地檔案d盤主目錄下的6個子目錄對應6中檔案,如 d 主目錄 001 2021 01 01 每個子目錄每天會產生乙個新的次子目錄並附帶一些內部檔案以當天日期命名如 d 主目錄 002 2021 01 01 xx,001則產生...
傳送與接收float資料
在寫硬體程式的時候,經常遇到要通過串列埠 can匯流排等傳送float型別的資料。由於mcu是以單個位元組為單位來傳送資料的,所以在遇到要傳送float,double這種占用多個位元組的資料型別的資料時,如果對指標的概念理解不到位,就很難實現。以float型別的資料為例,我的方法如下 傳送 void...
winsock程式設計如何設定傳送與接收超時引數?
在tcp通訊中,為了防止阻塞式呼叫send函式與recv函式時程式在這兩個函式處等待過久甚至一直等待,我們需要設定send函式與recv函式的超時時間長度。要達到這個目的,在winsock程式設計中,我們呼叫setsockopt來完成這個任務。int setsockopt sockets,intle...