2012-01-17 3 views
2

Windows에서 jedie's python ping implementation을 사용해 왔습니다. 나는 틀릴 수도 있지만 두 컴퓨터 (A와 B)를 별도의 스레드에서 ping 할 때 ping은 원본과 상관없이 수신 한 첫 번째 ping을 반환합니다.스레드에서 여러 개의 ips를 핑 (ping) 할 때 Python ICMP 핑 구현이 필요합니까?

jedie의 포크에서 문제가 될 수 있으므로 I reverted to the previous version입니다. (라인 134 또는 이와 유사한 것)

recPacket, addr = my_socket.recvfrom(1024) # Existing line 
print "dest: {}, recv addr: {}.".format(dest_addr, addr) # New line 

이 우리가 핑의 주소를 볼 수 있습니다 : 나는 receive_one_ping 코드의 라인에 추가

(이 버전은 내가 아래에 탐구거야입니다) 우리가 받고있어. (오른쪽, 대상 IP와 동일해야 하는가?)

테스트 :

ping1() 알려진 오프라인 IP (1.2.3.4),
ping2을 (핑) 알려진 온라인 IP를 핑 (192.168 3.1.1 - 내 라우터) 이제

>>> from ping import do_one 

>>> def ping1(): 
    print "Offline:", do_one("1.2.3.4",1) 

>>> ping1() 
Offline: None 

>>> def ping2(): 
    print "Online:", do_one("192.168.1.1",1) 

>>> ping2() 
Online: dest: 192.168.1.1, recv addr: ('192.168.1.1', 0). 
0.000403682590942 

우리가 함께 할 경우 : (편의상 타이머 사용)

>>> from threading import Timer 
>>> t1 = Timer(1, ping1) 
>>> t2 = Timer(1, ping2) 
>>> t1.start(); t2.start() 
>>> Offline:Online: dest: 192.168.1.1, recv addr: ('192.168.1.1', 0).dest: 1.2.3.4, recv addr: ('192.168.1.1', 0). 

0.0004508952953870.000423517514093 

그건 좀 망가, 그래서 여기에 (스레딩과 함께 잘 작동하지 않는 인쇄에 의한)이 조금 명확 :

>>> Online: dest: 192.168.1.1, recv addr: ('192.168.1.1', 0). 
Offline:dest: 1.2.3.4, recv addr: ('192.168.1.1', 0). # this is the issue - I assume dest should be the same as recv address? 

0.000450895295387 
0.000423517514093 

내 질문 :

    사람이를

  1. 다시 할 수 있습니까?

  2. 핑이 다음과 같이 작동해야합니까? 나는 그렇게 생각하지 않는다.

  3. 이 동작이없는 파이썬을위한 기존 ICMP 핑이 있습니까?
    또는 수신자 주소가 수신 주소와 일치 할 때까지 receive_one_ping을 폴링하는 등의 쉬운 수정 방법을 생각해 볼 수 있습니까?

편집 : 나는이 때문에 ICMP의 특성 일어나고있는 python-ping github page

답변

5

에 문제를 만들었습니다. ICMP에는 포트 개념이 없으므로 모두 ICMP 메시지는 모두 수신기에서 수신됩니다.

일반적으로 명확하게 구분하는 방법은 ICMP ECHO REQUEST 페이로드에 고유 식별자를 설정하고 응답에서 찾도록하는 것입니다. 이 코드는 그렇게 보이지만 현재 프로세스 ID를 사용하여 ID를 작성합니다. 이것은 다중 스레드 코드이므로 프로세스 ID를 공유하게되며 현재 프로세스의 모든 리스너는 모든 ECHO REPLY가 자신이 보낸 것이라고 생각할 것입니다!

do_one()의 변수를 ID으로 변경해야 스레드마다 고유하게 변경해야합니다.진정한 16 비트 해시 기능이 대안으로 작동 가능하게

my_ID = os.getpid() & 0xFFFF 

하지만, 이상적으로 사용한다 :

# add to module header 
try: 
    from thread import get_ident 
except ImportError: 
    try: 
     from _thread import get_ident 
    except ImportError: 
     def get_ident(): 
      return 0 

# now in do_one() body: 
my_ID = (get_ident()^os.getpid()) & 0xFFFF 

내가 돈을 '당신은 do_one()이 줄을 변경해야합니다 이 모듈에 다른 스레드 문제가 있는지는 알지 못하지만, 인 것처럼 보입니다.

제이드 구현을 사용하면 Ping()own_id 생성자 인수에 대해 유사한 변경을 수행합니다. 당신은 당신이 (위처럼) 고유 알고 id를 전달하고 Ping() 자신 개체를 관리하거나 생성자에서이 라인 (110)을 변경할 수 있습니다 수 있습니다 :

self.own_id = os.getpid() & 0xFFFF 

또한 추가 정보를 원하시면 this question and answer and answer comment thread를 참조하십시오.

+1

우수합니다. 감사합니다. 나는'receive_one_ping'가'packetID == ID'를 반환 할 때마다 각 스레드마다 하나의 응답 만 볼 수 있다고 생각합니다. 그리고 그들은 항상 같은 ID이므로 항상 첫 번째 응답을 반환합니다. 스레드가 do_one에 대한 매개 변수로 고유 한 ID를 전달하도록 할 것입니다 - threading.current_thread(). ident'을 시도하겠습니다. –

+0

아, 그게 정확히 맞습니다. 좋아,이 ident 문제는 ​​유일한 문제 일 가능성이 높습니다. jedie 구현을 선호한다면, 커스텀 id를'Ping()'생성자에 전달하는 한 수정없이 사용할 수 있습니다. –

+0

'threading.current_thread(). ident' 작동합니다 (스레드가 사용되지 않습니다.) : Online : id : 2688 ip : 192.168.1.1. dest : 192.168.1.1, recv addr : ('192.168.1.1', 0). 0.000427707990752 오프라인 : id : 5492 ip : 1.2.3.4 없음. 감사! –