Thread View: pl.comp.lang.python
8 messages
8 total messages
Started by królewna
Thu, 29 Apr 2010 11:02
Sockety, select i błąd
Author: królewna
Date: Thu, 29 Apr 2010 11:02
Date: Thu, 29 Apr 2010 11:02
48 lines
2755 bytes
2755 bytes
Witam
Dawno już nie pisałam bo nie miałam problemów póki co (za mało
testowania jak się okazało). Otóż mój błąd występuje, gdy nastąpi
połączenie na sockecie nieblokującym i próbuję coś z niego odczytać
przed otrzymaniem danych. Otóż następujący kod (jest to już kod
przykładowy a nie konkretnie wykorzystany):
socket.setdefaulttimeout(3)
listener = multiprocessing.connection.Listener(('localhost', 7000),
backlog = 100)
while 1:
(input, [], []) =
select.select([listener._listener._socket.fileno()],(),())
con = listener.accept()
lista.append(con)
ip = listener.last_accepted
#time.sleep(1)
print ip
try:
data = con.recv()
except Exception as e:
print "Wyjatek", e.args
con.close()
continue
con.close()
wyrzuca mi praktycznie caly czas wyjatek: "(11, 'Resource temporarily
unavailable')". Obie rzeczy (klient i serwer) są uruchamiane na
localhoscie więc opóźnienia są minimalne. Mimo wszystko wydaje się za
duże dla programu. Klient łaczy się i od razu wysyła dane dane również
od razu - bez żadnych opóźnień. Jednak zawsze dostaję ten błąd. Jeśli
odkomentuję zakomentowaną linijkę ze sleep(1) to naraz błędy mi znikają
i występują tylko jeśli w kliencie dam sleep między łaczeniem a
wysyłaniem na więcej niż 1 sekundę. Wygląda to tak jakby pomimo
ustawionego timeout'a żądanie odczytania danych następowało od razu i od
razu wyrzucany jest wyjątek jeśli to odczytanie nie nastąpi.
Jednocześnie sockety blokujące w ogóle mnie nie interesują i nie wchodzą
w grę. Chodzi o to, że będę masowo odbierała połączenia, które muszą być
obsłużone jak najszybciej i w przypadku jeśli socket mi się zatrzyma na
jakimś połączeniu, którego client nagle straci połączenie to będzie mi
wisiał na tym połączeniu.
Czy jest jakiś sposób aby to elegancko rozwiązać?
pozdrawiam,
królewna
Re: Sockety, select i błąd
Author: Daniel Mróz
Date: Thu, 29 Apr 2010 12:59
Date: Thu, 29 Apr 2010 12:59
59 lines
2931 bytes
2931 bytes
On 29.04.2010, =?UTF-8?B?a3LDs2xld25h?= <królewna@ee.pl> wrote:
> Dawno już nie pisałam bo nie miałam problemów póki co (za mało
> testowania jak się okazało). Otóż mój błąd występuje, gdy nastąpi
> połączenie na sockecie nieblokującym i próbuję coś z niego odczytać
> przed otrzymaniem danych. Otóż następujący kod (jest to już kod
> przykładowy a nie konkretnie wykorzystany):
>
> socket.setdefaulttimeout(3)
> listener = multiprocessing.connection.Listener(('localhost', 7000),
> backlog = 100)
> while 1:
> (input, [], []) =
> select.select([listener._listener._socket.fileno()],(),())
Wywal ten socket.setdefaulttimeout(3), dodaj czwarty argument do select.select()
o wartości 3.0 i zobacz czy mu się poprawi. Pamiętaj o obsłudze timeoutu.
BTW, skąd pewność że socket jest w trybie nieblokującym? Nie widzę żebyś
gdzieś ustawiała setblocking(0), a z multiprocessing.connection.Listener
nie miałem do czynienia.
> con = listener.accept()
> lista.append(con)
> ip = listener.last_accepted
> #time.sleep(1)
> print ip
> try:
> data = con.recv()
> except Exception as e:
> print "Wyjatek", e.args
> con.close()
> continue
> con.close()
Oj, jeśli gadasz po TCP (AF_INET, SOCK_STREAM), to musisz jeszcze popracować nad
tym kodem. W takim przypadku recv() może nie zwrócić wszystkich przesyłanych danych
i zamkniesz socket zanim odbierzesz wszystko. Dane powinnaś zczytywać do czasu, aż
nie dostaniesz nic. Będzie to oznaczało, że nadawca skończył. Zazwyczaj wygląda to
mniej więcej tak:
data = ''
while 1:
fromsock = sock.recv()
if fromsock:
data += fromsock
continue
break
sock.shutdown(2) # tego też nie robisz, a powinnaś
sock.close()
> Czy jest jakiś sposób aby to elegancko rozwiązać?
Użyć select.poll().
Pozdrawiam
Beorn
--
Daniel 'Beorn' Mróz <beorn@alpha.pl> http://127.0.0.1/beorn
[GIT d s:- a-@ C++++ UL++++$ P+ L++++ E--- W+ N+++ o? K- w---]
[O- M- V! PS+ PE++ Y+ PGP++ t- 5 X R !tv b+ DI D++ G++ e h*]
[ r++ y+ ]
Re: Sockety, select i błąd
Author: i0cus
Date: Sat, 01 May 2010 11:31
Date: Sat, 01 May 2010 11:31
71 lines
4034 bytes
4034 bytes
Witam,
Trochę strzelam w ciemno, ale nie mam jak sprawdzić w tej chwili,
możliwe, że zupełnie od rzeczy. ;-)
On 29 Kwi, 14:59, Daniel Mróz <be...@alpha.pl> wrote:
> On 29.04.2010, =?UTF-8?B?a3LDs2xld25h?= <króle...@ee.pl> wrote:> Dawno już nie pisałam bo nie miałam problemów póki co (za mało
> > testowania jak się okazało). Otóż mój błąd występuje, gdy nastąpi
> > połączenie na sockecie nieblokującym i próbuję coś z niego odczytać
> > przed otrzymaniem danych. Otóż następujący kod (jest to już kod
> > przykładowy a nie konkretnie wykorzystany):
>
> > socket.setdefaulttimeout(3)
> > listener = multiprocessing.connection.Listener(('localhost', 7000),
> > backlog = 100)
> > while 1:
> > (input, [], []) =
> > select.select([listener._listener._socket.fileno()],(),())
>
> Wywal ten socket.setdefaulttimeout(3), dodaj czwarty argument do select.select()
> o wartości 3.0 i zobacz czy mu się poprawi. Pamiętaj o obsłudze timeoutu.
> BTW, skąd pewność że socket jest w trybie nieblokującym? Nie widzę żebyś
> gdzieś ustawiała setblocking(0), a z multiprocessing.connection.Listener
> nie miałem do czynienia.
A czy to przypadkiem nie działa tak, że serwerowy socket jak jest
readable to można zrobić nieblokującego accept(), a żeby wołać na nim
recv() powinien być readable drugi raz? Timeout w select na 0 i będzie
szybko.
> > con = listener.accept()
> > lista.append(con)
> > ip = listener.last_accepted
> > #time.sleep(1)
> > print ip
> > try:
> > data = con.recv()
> > except Exception as e:
> > print "Wyjatek", e.args
> > con.close()
> > continue
> > con.close()
>
> Oj, jeśli gadasz po TCP (AF_INET, SOCK_STREAM), to musisz jeszcze popracować nad
> tym kodem. W takim przypadku recv() może nie zwrócić wszystkich przesyłanych danych
> i zamkniesz socket zanim odbierzesz wszystko. Dane powinnaś zczytywać do czasu, aż
> nie dostaniesz nic. Będzie to oznaczało, że nadawca skończył. Zazwyczaj wygląda to
> mniej więcej tak:
>
> data = ''
> while 1:
> fromsock = sock.recv()
> if fromsock:
> data += fromsock
> continue
> break
> sock.shutdown(2) # tego też nie robisz, a powinnaś
> sock.close()
IIRC nieblokujący socket zdaje się zwróci pustego stringa, jeśli nic
nie ma w buforze, bo musi zwrócić od razu. Co prawda od dwóch lat
używam tylko Twisted, ale wydaje mi się, że jeśli jest gniazdo
oznaczone jako readable przez select i zwróci nic, to wtedy nadawca
zakończył wysyłanie.
--
pozdrawiam,
SMG
Re: Sockety, select i błąd
Author: królewna
Date: Wed, 05 May 2010 06:29
Date: Wed, 05 May 2010 06:29
43 lines
2720 bytes
2720 bytes
W dniu 29.04.2010 14:59, Daniel Mróz pisze: > Wywal ten socket.setdefaulttimeout(3), dodaj czwarty argument do select.select() > o wartości 3.0 i zobacz czy mu się poprawi. Pamiętaj o obsłudze timeoutu. > BTW, skąd pewność że socket jest w trybie nieblokującym? Nie widzę żebyś > gdzieś ustawiała setblocking(0), a z multiprocessing.connection.Listener > nie miałem do czynienia. Niestety mi to nie bardzo pasuje, bo 3 sekundy na select'cie to dużo. Pomijając fakt, że zrobienie tego w ten sposób powoduje, że program wisi mi nie na select'cie a na listener.accept() co jest chyba zupełnie bez sensu. A socket jest ustawiany w tryb nonblocking gdy tylko ustawi się defaulttimeout na coś różnego od 0.0 (w moim przypadku 3). > Oj, jeśli gadasz po TCP (AF_INET, SOCK_STREAM), to musisz jeszcze popracować nad > tym kodem. W takim przypadku recv() może nie zwrócić wszystkich przesyłanych danych > i zamkniesz socket zanim odbierzesz wszystko. Dane powinnaś zczytywać do czasu, aż > nie dostaniesz nic. Będzie to oznaczało, że nadawca skończył. Zazwyczaj wygląda to > mniej więcej tak: > > data = '' > while 1: > fromsock = sock.recv() > if fromsock: > data += fromsock > continue > break > sock.shutdown(2) # tego też nie robisz, a powinnaś > sock.close() > Dlatego mówiłam, że to tylko przykładowy kod, który ma za zadanie wywołanie tego błędu a nie poprawne działanie. >> Czy jest jakiś sposób aby to elegancko rozwiązać? > Użyć select.poll(). Z tego co czytałam i próbowałam, to select.poll() dla mnie nic nie zmieni więc to nie jest rozwiązanie ;) -- pozdrawiam królewna
Re: Sockety, select i błąd
Author: królewna
Date: Wed, 05 May 2010 06:32
Date: Wed, 05 May 2010 06:32
14 lines
1440 bytes
1440 bytes
W dniu 01.05.2010 13:31, i0cus pisze: > > A czy to przypadkiem nie działa tak, że serwerowy socket jak jest > readable to można zrobić nieblokującego accept(), a żeby wołać na nim > recv() powinien być readable drugi raz? Timeout w select na 0 i będzie > szybko. > Dokładnie jest tak jak mówisz. Tyle, że timeout 0 w select'cie dalej powoduje, że mam ten sam błąd. -- pozdrawiam, królewna
Re: Sockety, select i błąd
Author: Łukasz Rekucki
Date: Wed, 05 May 2010 07:15
Date: Wed, 05 May 2010 07:15
23 lines
2087 bytes
2087 bytes
On 5 Maj, 08:32, krĂłlewna <króle...@ee.pl> wrote: > W dniu 01.05.2010 13:31, i0cus pisze: > > > > A czy to przypadkiem nie działa tak, że serwerowy socket jak jest > > readable to można zrobić nieblokującego accept(), a żeby wołać na nim > > recv() powinien być readable drugi raz? Timeout w select na 0 i będzie > > szybko. > > Dokładnie jest tak jak mówisz. Tyle, że timeout 0 w select'cie dalej > powoduje, że mam ten sam błąd. accept() zwraca *nowy* socket, który należy dodać do listy przekazywanej do select() i dopiero jak select() stwierdzi, że ten nowy socket jest gotowy do czytania można z niego bezpiecznie skorzystać (oczywiście tylko raz i niekoniecznie przeczytamy wszystkie wysłane dane). > > -- > pozdrawiam, > królewna
Re: Sockety, select i błąd
Author: królewna
Date: Wed, 05 May 2010 08:24
Date: Wed, 05 May 2010 08:24
30 lines
2516 bytes
2516 bytes
W dniu 05.05.2010 09:15, Łukasz Rekucki pisze:
>
> accept() zwraca *nowy* socket, który należy dodać do listy
> przekazywanej do select() i dopiero jak select() stwierdzi, że ten
> nowy socket jest gotowy do czytania można z niego bezpiecznie
> skorzystać (oczywiście tylko raz i niekoniecznie przeczytamy wszystkie
> wysłane dane).
Dokładnie tak robię. A za dokumentacją multiprocessing.connection
recv()
Return an object sent from the other end of the connection using
send(). Raises EOFError if there is nothing left to receive and the
other end was closed.
Z czego rozumiem, że za jednym recv() powinnam odczytać wszystko, co
zostało wysłane przy pomocy jednego send(). Jeśli nic nie wysłałam przez
send() to powinnam dostać EOFError.
Specjalnie dla tych metod wysyłam sobie tablicę 100k elementową aby to
sprawdzić. Przy "niedługich" danych (tablica 20k elementowa)jest ok
jednak przy tablicy 30k elementowej jest już błąd. Skąd mam wiedzieć
jaki jest limit danych, które mogę wysłać? Pół biedy jeśli jest to jakiś
limit zaimplementowany na stałe (choć i to by było niesmaczne) ale co
jeśli to jest błąd związany np z aktualną przepustowością sieci (a ja
przesyłam póki co dane w obrębie localhosta więc sieć jest tu
praktycznie najszybsza jaka będzie:) )?
--
pozdrawiam
królewna
Re: Sockety, select i błąd
Author: królewna
Date: Wed, 05 May 2010 08:29
Date: Wed, 05 May 2010 08:29
8 lines
1413 bytes
1413 bytes
I poprawka, jeśli np tą 20k elementową tablicę wysyłam jako pierwszą a później jakiś krótki tekst to przy tej tablicy otrzymuję "Resource temporarily unavailable". Nie za bardzo już wiem jak to mam łapać i właściwie na czym polega błąd. -- pozdrawiam królewna
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads