2016-08-25 20 views
5

ファイルから画像にアクセスしてエンコードし、サーバーに送信するプログラムを作成します。 サーバーはイメージをデコードしてファイルに保存することになっています。 イメージのエンコード自体をテストしたところ、問題はサーバーとクライアントの接続にあります。ここでPythonエラー:画像を送信するときに「socket.error:[Errno 11] Resource temporarily unavailable」と表示されます

はサーバです:

import socket 
import errno 
import base64 

from PIL import Image 
import StringIO 

def connect(c): 
    try: 
     image = c.recv(8192) 
     return image 
    except IOError as e: 
     if e.errno == errno.EWOULDBLOCK: 
      connect(c) 


def Main(): 
    host = '138.106.180.21' 
    port = 12345 

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) 
    s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 
    s.bind((host, port)) 
    s.listen(1) 


    while True: 

     c, addr = s.accept() 
     c.setblocking(0) 

     print "Connection from: " + str(addr) 

     image = c.recv(8192)#connect(c) 

     imgname = 'test.png' 

     fh = open(imgname, "wb") 
     if image == 'cusdom_image': 
      with open('images.png', "rb") as imageFile: 
       image = '' 
       image = base64.b64encode(imageFile.read()) 
       print image 
     fh.write(image.decode('base64')) 
     fh.close() 


if __name__ == '__main__': 
    Main() 

そして、ここでは、クライアントである:

import socket 
import base64 

from PIL import Image 
import StringIO 
import os, sys 

ip = '138.106.180.21' 
port = 12345 
print 'Add event executed' 
s = socket.socket() 
s.connect((ip, port)) 

image_path = '/home/gilgamesch/Bilder/Bildschirmfoto.png' 

print os.getcwd() 
olddir = os.getcwd() 
os.chdir('/') 
print os.getcwd() 

if image_path != '': 
    with open(image_path, "rb") as imageFile: 
     image_data = base64.b64encode(imageFile.read()) 
     print 'open worked' 
else: 
    image_data = 'cusdom_image' 

os.chdir(olddir) 

s.send(image_data) 


s.close() 

、エラーメッセージは次のとおりです。あなたは、リモート設定されているサーバーで

Traceback (most recent call last): 
    File "imgserv.py", line 49, in <module> 
    Main() 
    File "imgserv.py", line 34, in Main 
    image = c.recv(8192)#connect(c) 
socket.error: [Errno 11] Resource temporarily unavailable 

答えて

8

ソケット(これはaccept()によって返されます)をノンブロッキングモードにします。つまり、そのソケットのI/Oは即時終了します読み込むデータがない場合は例外でyを返します。

通常、サーバーとの接続を確立してからクライアントによって送信されるイメージデータとの間に一定の時間があります。接続が受け入れられたら、サーバーはクライアントからすぐにデータを読み取ろうとしますが、まだ読み取るデータがない可能性があります。したがって、c.recv()socket.error: [Errno 11] Resource temporarily unavailable例外を発生させます。 Errno 11はEWOULDBLOCKに対応しているため、読み取る準備のできたデータがないため、recv()が中止されました。

whileループの先頭にaccept()があるため、一度に1つの接続しか処理できないため、コードにはノンブロッキングソケットが必要ないようです。 c.setblocking(0)への呼び出しを削除するだけで、この問題は解決します。

+0

サーバーは複数の接続を取得する必要がありますか? –

+0

それは別の問題です。 'select()'を使うと、複数のソケットのうちどれが読み込み準備が整っているかを知ることができ、それらのソケットに対して 'recv()'を呼び出すことができます。 'select()'に渡されたソケットのリストにメインサーバソケットを追加し、 'select()'が読み込み可能であることを示すときはいつでもそのソケットでacceptを呼び出します。 'select'モジュールには' poll() 'などの選択肢があります。 al。 – mhawke

+1

また、['selectors'](https://docs.python.org/3/library/selectors.html#module-selectors)モジュールまたは[' asyncio'](https://docs.python .org/3/library/asyncio.html#module-asyncio)を使用しています。 ['asyncore'](https://docs.python.org/2.7/library/asyncore.html#module-asyncore)は、Python 2のオプションです。 – mhawke

関連する問題