2016-03-18 18 views
1

Python'da, engellemeyi engellemediğim bir yuvada socket.connect() kullanmak istiyorum. Bunu yapmaya çalıştığımda, yöntem her zaman bir BlockingIOError atar. Hatayı görmezden geldiğimde (aşağıdaki gibi) program beklendiği gibi yürütülür. Soketi bağlandıktan sonra engellemeyi engellediğinde, hata yoktur. Soketin okunabilir veya yazılabilir olduğundan emin olmak için select.select() öğesini kullandığımda hala hatayı alıyorum.Bloke olmayan bir soket ile bağlantı nasıl yapılır?

testserver.py

import socket 
import select 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.setblocking(0) 

host = socket.gethostname() 
port = 1234 

sock.bind((host, port)) 
sock.listen(5) 

while True: 
    select.select([sock], [], []) 
    con, addr = sock.accept() 
    message = con.recv(1024).decode('UTF-8') 
    print(message) 

testclient.py

import socket 
import select 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.setblocking(0) 

host = socket.gethostname() 
port = 1234 

try: 
    sock.connect((host, port)) 
except BlockingIOError as e: 
    print("BlockingIOError") 

msg = "--> From the client\n" 

select.select([], [sock], []) 
if sock.send(bytes(msg, 'UTF-8')) == len(msg): 
    print("sent ", repr(msg), " successfully.") 

sock.close() 

terminali 1

$ python testserver.py 
--> From the client 

terminali 2

$ python testclient.py 
BlockingIOError 
sent '--> From the client\n' successfully. 

Bu kod ilk bağlantı üzerinde BlockingIOError() hariç doğru çalışır. Hata belgelerine şu şekilde okunur: Raised when an operation would block on an object (e.g. socket) set for non-blocking operation.

Bloke etmek için bir soket seti ile doğru şekilde() nasıl bağlarım? Connect() 'i bloke etmeden yapabilir miyim? Ya da hatayı görmezden gelmek uygun mu?

+0

Bu bağlantı size yardımcı olabilir: http://stackoverflow.com/questions/1205863/how-can-i-get-non-blocking-socket-connects – akash12300

+0

@ Akash1993 evet, daha önce bu soruya baktığımda basit örneğimle ilgili zor bir zaman geçirdim. Asyncio'dan kaçınmak istiyorum; Fazlalık görünüyor. Hata oluştuğunu açıklığa kavuşturur çünkü bloke etmemesi gerektiğinde (blockingioerror dokümantasyonu ile birlikte). Soru daha 'connect()' non-blocking 'yapmak için bir yol var. – MikeJava

cevap

0

burada hüner seçme ardından ilk kez, tamamladığında tekrar sock.connect çağırmanız gerekir olmasıdır. connect'dan başarılı bir geri dönüş durumu alıncaya kadar soket bağlı değil.

Sadece select tamamlanıncaya kadar ilk çağrı sonra bu iki çizgileri ekleyin:

print("first select completed") 
sock.connect((host, port)) 

DÜZENLEME:
İzleyen. sock.connect numaralı telefona ek bir aramanın gerekli olduğunu belirtmek yanlıştı. Ancak, kendi kod yolunda bağlantı hatasını işlemek isterseniz, connect numaralı özgün engelleme çağrısının başarılı olup olmadığını anlamak için iyi bir yoldur.

C kodunda bu ulaşmada geleneksel yolu burada açıklanmıştır: Async connect and disconnect with epoll (Linux)

Bu getsockopt çağıran içerir. Bunu python'da da yapabilirsiniz, ancak sock.getsockopt'dan geri döndüğünüz sonuç bytes nesnesidir. Ve eğer bir başarısızlığı temsil ederse, o zaman onu bir errno tamsayısına dönüştürmeniz ve bir dizgeye (ya da sorunu dış dünyaya iletmek için neye ihtiyacınız olursa olsun) eşleştirmeniz gerekir. sock.connect numaralı telefonu çağırmak, errno değerini zaten uygun bir özel durumla eşler.

Çözüm 2: Ayrıca sadece connect tamamladı sonra kadar sock.setblocking(0) arayarak erteleyebilir.

+1

Gönderdiğim kod, olması gerektiği gibi çalışıyor ve bu konuda daha açık olması için soruyu düzenledim. Sorun, bağlantının başarısına değil, ilk bağlantıya attığı BlockingIOError'dır. Gönderdiğim terminal çıktılarını incelerseniz, belki daha açık olacaktır. – MikeJava

+0

Çözüm 2 kesinlikle doğrudur! Aslında benim soruma değindim; Bunu yapmak için bir yol olup olmadığını merak ediyorum * soket engellemeye ayarlandıktan sonra. – MikeJava

+0

Bunu izlemiyorum. "Engelleyici olmayan bir davranış istediğimde, engelleme davranışı elde etmenin bir yolu var mı?" Diye soruyor gibisiniz. 'Sock.setblocking (0)' olarak adlandırılmazsanız, varsayılan davranış engellenir. –

İlgili konular