Seite 1 von 1

select.select() - falsches verhalten

Verfasst: Donnerstag 29. Januar 2009, 09:45
von Mad-Marty
Hallo,

ich habe ein eher seltsames problem mit select.select socket multiplexing.

Ich versuche, ca 100 pings parallel zu verschicken, klappt auch prima,
allerdings sind die empfangenen echo's alle die gleichen, bzw alle von 1-2 hosts.

Weiss jemand wieso es zu dem phenomen kommt?

hier hab ich das ganze nochmal extrem gekürzt und dirty neu geschrieben, selbes ergebnis wie die "richtige" variante.

In den prints sieht man das alle antworten von 1-2 ip's kamen statt ~ 100 verschiedene.


getestet auf Python 2.4.4 win32 / linux32

Code: Alles auswählen

from socket import *
import select
import time

ping_pkt = '\x08\x00\xb2\xe4\x12\x90\x00\x00 -HELLO HOST-  -HELLO HOST-  -HELLO HOST-  -HELLO HOST- '

def ping1host(ip):
   s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)
   s.sendto(ping_pkt, (ip, AF_INET))
   print s.recvfrom(512)

   sockets = [socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) for ip in ips]
   for i, s in enumerate(sockets):
      s.sendto(ping_pkt, (ips[i], AF_INET))
   deadline = time.time() + timeout
   while time.time() < deadline:
      r, w, e = select.select(sockets, [], [], 0)
      for s in r:
         print s.recvfrom(512)
      

         
ips = [
# a few ip's (100)
]
   
if __name__ == '__main__':
   ping1host('127.0.0.1')
   ping_many(ips)

Verfasst: Donnerstag 29. Januar 2009, 09:54
von rayo
Hi

Ich kann nur rate, da ichs jetzt nicht testen kann.
Gib mal kein Timeout beim select an.
Zusätzlich weiss ich nicht, wie das ICMP Protokoll so viele gleichzeitige Pings behandelt, probier mal zuerst wenige Pings gleichzeitig und dann immer schrittweise erhöhen.


Gruss

Verfasst: Donnerstag 29. Januar 2009, 10:03
von Mad-Marty
Hi,

das ändert leider nichts, auserdem wieso krieg ich 500 ergebnisse für 100 hosts, da stimmt doch was nicht.

Nur hab ich keine Ahnung was, ein gelesener socket ist ja nicht mehr "read-ready" - sollte jedenfalls so sein.

Also ich werd das gefühl nicht los select ist verbuggt, oder ein paar wichtige hinweise sind nicht dokumentiert.

Sieht so aus als wenn Select die sockets nicht richtig auseinanderhält und irgendwie alle sockets die selben daten lesen.

Verfasst: Donnerstag 29. Januar 2009, 10:11
von rayo
Hi

In select ist kein Fehler. Ich denke ICMP ist das Problem, ICMP hat keine Ports und somit kann er die 100 Pings nicht voneinander halten.

Probier doch einmal nur 1 Socket mit 100 Pings zu verschicken und schau was dann heraus kommt.

Gruss

Verfasst: Donnerstag 29. Januar 2009, 11:11
von Mad-Marty
Gute Idee,
und das beste, damit funktioniert select.select auch wie erwartet. :D

Danke für den Vorschlag.

Das Schnipsel da unten scheint richtig zu funktionieren.
Fassen wir mal zusammen,

- select kommt mit non-port sockets nicht klar
- ausser man sendet alles über einen socket

Irgendwie sollte das doch aber mal dokumentiert werden das select mit mehreren raw sockets und ohne port (wie icmp) nicht funktioniert ...

Indirekt hab ich noch herausgefunden das beim original jede antwort von jedem der sockets 1 mal gelesen wird, daher die grosse anzahl an responses.

Code: Alles auswählen

def ping_many(ips, timeout=3.0):
   s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)
   for ip in ips:
      s.sendto(ping_pkt, (ip, AF_INET))
   deadline = time.time() + timeout
   while time.time() < deadline:
      r, w, e = select.select([s], [], [], 0)
      for s in r:
         print s.recvfrom(512)

Verfasst: Donnerstag 29. Januar 2009, 11:55
von rayo
Hi

Aber das ist kein Problem von select sondern von ICMP, gleichzeitige PINGs über verschiedene Sockets geht nicht gut, auch ohne select, weil er nicht richtig Unterscheiden kann für welchen Socket die Antwort war, weil jeder Socket gleich ist.

Gruss

Verfasst: Donnerstag 29. Januar 2009, 13:38
von Mad-Marty
Stimmt nicht ganz, rayo.

Ich habe seit 2 jahren nen multithreaded ping mit mehreren sockets im einsatz, da hat das prima geklappt ohne select.

Verfasst: Donnerstag 29. Januar 2009, 22:00
von rayo
Hi

Habs jetzt getestet, geht auch mit mehreren Sockets, nur müssen die sockets, welche bereits gelesen wurden aus der sockets Liste gelöscht werden. Wahrscheinlich liest man dann mehrmals den gleichen Socket.

Man sieht das Verhlaten auch, wenn man 100 Sockets erstellt und jeweils ein Ping darüber verschickt aber nur den ersten Socket ausliest. Da kommen dann alle Antworten auf dem ersten Socket obwohl man 100 verschiedene Sockets zum Senden gebraucht hat.

Also kann man bei ICMP nicht sicher sein, über welchen Socket die Antwort wirklich reinkommt, darum kann man auch noch Daten mitschicken, um die Antworten zum entsprechenden Socket zuzuteilen.

Gruss

Verfasst: Freitag 30. Januar 2009, 12:20
von Mad-Marty
komisch, bei mir spielte das keine rolle ob ich immer die ganze socketliste nehme oder die gelesenen entferne.

Auf was für einen sys und python version hast du getestet?

Verfasst: Freitag 30. Januar 2009, 13:50
von rayo
Win Vista SP1 mit python2.5