web-dev-qa-db-ja.com

Python error: "socket.error:[Errno 11]リソースが一時的に利用できません"画像送信時

ファイルの画像にアクセスし、それらをエンコードし、サーバーに送信するプログラムを作成したいと思います。サーバーが画像をデコードしてファイルに保存することになっているよりも。画像のエンコード自体をテストしましたが、うまくいきました。そのため、問題はサーバーとクライアントの接続にあります。

サーバーは次のとおりです。

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は例外によって直ちに終了します。

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

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

14
mhawke