2016-08-25 17 views
5

Chcę utworzyć program, który uzyskuje dostęp do obrazów z plików, koduje je i wysyła je na serwer. Niż serwer ma zdekodować obraz i zapisać go do pliku. Przetestowałem kodowanie obrazu i zadziałało, więc problem leży w połączeniu z serwerem i klientem.Błąd w języku Python: "socket.error: [Errno 11] Zasoby chwilowo niedostępne" podczas wysyłania obrazu

Oto server:

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() 

I tu jest klient:

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() 

a komunikat o błędzie jest:

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 

Odpowiedz

8

W serwerze ustawiania pilota gniazdo (zwrócone przez accept()) do trybu bez blokowania, co oznacza, że ​​wejścia/wyjścia na tym gnieździe zakończą się natychmiastowo y przez wyjątek, jeśli nie ma danych do odczytania.

Zwykle pomiędzy ustanowieniem połączenia z serwerem i danymi obrazu przesyłanymi przez klienta zwykle występuje pewien okres czasu. Serwer podejmie próbę natychmiastowego odczytania danych od klienta po zaakceptowaniu połączenia, jednak może nie być jeszcze żadnych danych do odczytania, więc wywołuje wyjątek od . Errno 11 odpowiada EWOULDBLOCK, więc recv() zostało przerwane, ponieważ nie było danych gotowych do odczytania.

Twój kod prawdopodobnie nie wymaga gniazd bez blokady, ponieważ na górze pętli while znajduje się accept(), więc tylko jedno połączenie może być obsługiwane jednocześnie. Możesz po prostu usunąć połączenie z numerem c.setblocking(0), a ten problem powinien zniknąć.

+0

ale co mam zrobić, jeśli serwer ma uzyskać wiele połączeń? –

+0

To kolejny problem. Możesz użyć 'select()', aby określić, które z wielu gniazd jest gotowe do odczytu, a następnie wywołaj 'recv()' na tych, które są. Dodałbyś także główne gniazdo serwera do listy gniazd przekazanych do 'select()' i wywołaj accept w tym gnieździe za każdym razem, gdy 'select()' wskazuje, że jest czytelne. Istnieją alternatywy w module 'select', takie jak' poll() 'et. glin. – mhawke

+1

Możesz także rozważyć użycie modułu ['selectors'] (https://docs.python.org/3/library/selectors.html#module-selectors) lub [' asyncio'] (https: //docs.python .org/3/library/asyncio.html # module-asyncio) jeśli używasz Pythona 3.4 lub nowszego. ['asyncore'] (https://docs.python.org/2.7/library/asyncore.html#module-asyncore) to opcja na Pythonie 2. – mhawke

Powiązane problemy