select.select() - falsches verhalten

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

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)
Zuletzt geändert von Mad-Marty am Donnerstag 29. Januar 2009, 11:05, insgesamt 2-mal geändert.
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

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
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

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.
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

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
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

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)
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

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
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Stimmt nicht ganz, rayo.

Ich habe seit 2 jahren nen multithreaded ping mit mehreren sockets im einsatz, da hat das prima geklappt ohne select.
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

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
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

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?
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Win Vista SP1 mit python2.5
Antworten