差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

Both sides previous revision 前次修改
下次修改
前次修改
python:socket:send_resource_temporarilty_unvailable_error [2016/09/12 14:08]
tony [How to?]
python:socket:send_resource_temporarilty_unvailable_error [2023/06/25 09:48] (目前版本)
行 51: 行 51:
 [Errno 11] Resource temporarilty unavaliable [Errno 11] Resource temporarilty unavaliable
 </​code>​ </​code>​
-===== How to? =====+===== Diagnosis ​===== 
 +==== 實驗1 - 分批送+sleep ​====
 首先我發現接收到的檔案大小一定是33304 bytes,於是我加了以下程式做試驗:​ 首先我發現接收到的檔案大小一定是33304 bytes,於是我加了以下程式做試驗:​
 <code python> <code python>
行 69: 行 70:
  if not data: break  if not data: break
  conn.send(data)  conn.send(data)
- time.sleep(0.001)+ time.sleep(0.000001
 +</​code>​ 
 +以每次1024 bytes發送,每次中間等待0.001秒,如此就能順利完成發送。但問我無法確定是由於send data thread搶了所有執行資源,造成buffer無法清空的問題;還是由於清buffer就是比較慢。在無法確認實際原因情況下,這方法我不敢使用。 
 +==== 實驗2 - Remove settimeout ==== 
 +在remove settimeout後,就可以正常傳送與接收資料;沒設定timeout等效於setblocking(1)。 
 +==== 實驗3 - setdefaulttimeout ==== 
 +我在建立socket前,使用socket.setdefaulttimeout(60),發現可以正常傳送與接收資料。這挺奇怪的,我還不曉得這與settimeout有何不同。 
 +==== 實驗4 - 使用strace去跑分批送 ==== 
 +與實驗1的區別在於,我移除sleep並透過strace去執行也可以正常執行完畢。 
 +<code bash> 
 +strace -o output.txt -s512 python test.py 
 +</​code>​ 
 +我猜測透過strace可能也造成send資料之間的延遲,好讓buffer有足夠時間釋放。 
 +===== How to resolve? ===== 
 +根據實驗結果,有以下結論:​ 
 +  - 實驗二說明在blocking mode下,sendall應能正常傳送資料。實驗三為例外,原因還不明。 
 +  - 實驗一與四說明,如果將send分批進行且有緩衝,應能正常傳送資料。 
 +  - 並非所有OS有相同結果,可能與python或內核有關。 
 +綜合以上,如果要設定timeout,安全作法應該使用non-blocking IO的存取方式。因此參考[[https://​vaidik.in/​blog/​understanding-non-blocking-io-with-python-part-1.html|此篇文章]]修改程式碼,針對Resource temporarilty unavaliable錯誤retry:​ 
 +<code python>​ 
 +def sendData(sock,​ data): 
 + total_sent = 0 
 + while len(data):​ 
 + try: 
 + sent = sock.send(data) 
 + total_sent += sent 
 + data = data[sent:​] 
 + print '​Sending data'​ 
 + except socket.error,​ e: 
 + if e.errno != errno.EAGAIN:​ 
 + raise e 
 + print '​Blocking with', len(data), '​remaining'​ 
 + select.select([],​ [sock], [])   
 + return total_sent 
 +</​code>​ 
 +呼叫程式改為:​ 
 +<code python>​ 
 +data = debugfile.read() 
 +total_data = len(data) 
 +total_send = sendData(conn,​ data) 
 +print "data size = %s, send size = %s" % (total_data,​ total_send)
 </​code>​ </​code>​
-以每次1024 bytes發送,每次中間等待0.001秒,如此就能順利完成發送。 
- 
 ===== Reference ===== ===== Reference =====
   * [[https://​fwengineer.blogspot.tw/​2013/​05/​setsockopt.html|setsockopt]]   * [[https://​fwengineer.blogspot.tw/​2013/​05/​setsockopt.html|setsockopt]]
   * [[http://​stackoverflow.com/​questions/​6645851/​multiprocessing-manager-rlock-error|multiprocessing > Manager() > RLock Error:]]   * [[http://​stackoverflow.com/​questions/​6645851/​multiprocessing-manager-rlock-error|multiprocessing > Manager() > RLock Error:]]
   * [[https://​github.com/​patmun/​pynetdicom/​pull/​47|introduce configurable client socket receive timeout]]   * [[https://​github.com/​patmun/​pynetdicom/​pull/​47|introduce configurable client socket receive timeout]]
 +  * [[https://​docs.python.org/​2/​library/​socket.html|python doc - socket]]
 +  * [[https://​vaidik.in/​blog/​understanding-non-blocking-io-with-python-part-1.html|Understanding Non Blocking I/O with Python - Part 1]]