2011-12-13 4 views
0

, 그래서 ... 배려하십시오. 필요한 권한이 있습니다. 파이썬 ICMP 원시 소켓 구현

는 이제 서버 내가 그렇게 정의 :

host = socket.gethostbyname(socket.gethostname()) 
address = (host, 22224) 
sockSer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) 
sockSer.bind(address) 
sockSer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) 
packet, addr = sockSer .recvfrom(4096) # wait for packet from client 

Q1) 이유는 간단하게 입력 할 수 없습니다 : 호스트 = '로컬 호스트'를. 이렇게하면 줄 작성을 허용하지 않습니다. sockSer.ioctl (socket.SIO_RCVALL, socket.RCVALL_ON). 서버가 내 클라이언트의 메시지를받지 못합니다. gethostbyname (socket.gethostname())을 수행 할 때만 192.168.1.101 이 나온 다음 작동합니다. 다른 클래스에서

: 클라이언트 소켓 :

host = socket.gethostbyname(socket.gethostname()) 
address = (host, 22224) 
sockCli = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) 

Q2) 내가 또한 입력해야 할 : sockCli.ioctl (socket.SIO_RCVALL, socket.RCVALL_ON를) 아니면 sockCli . 연결 (주소)? connect 명령없이 작동하는 것 같습니다. 클라이언트 소켓에 대해 ? 1) 클라이언트에서 서버로 패킷을 전송 :

header=... 
payload='a' 
sockCli.sendto(header + payload, address) 

2) 서버에 패킷을 수신하고 클라이언트로 뭔가를 보내

while(true): 
    data, addr = sockSer.recvfrom(4096) 
    header2=... 
    payload2='b' 
    sockSer.sendto(header2 + payload2, addr) 

이제 문제는 내가 다음 작업을 수행 할 때 발생

이제 내 중요한 질문은 다음과 같습니다. Q3) 서버가 페이로드 'b'를 사용하여 클라이언트에 단 하나의 패킷 만 보냈습니다. 이다 무슨 , 내 클라이언트는 실제로 while 루프에서이 패킷을 수신 : 첫 번째 패킷이 클라이언트 자체가 서버로 전송 무엇이고, 다른 패킷이 클라이언트가 서버에서 가져온 것입니다. 따라서 내 출력은 단순히 'b'대신 'ab'입니다. 왜 이런 일이 발생합니까 ???

참고 : 나는 전체 코드를 입력하지 않은,하지만 난 등등 내 문법, 구문 분석, 헤더 구성을 생각 정확합니다. 내 코드에 명백한 문제가 있습니까? 필요한 경우 전체 코드를 업로드합니다.

감사합니다.

+0

원시 소켓은 시스템이 허용하지 않는 한 루프백 인터페이스에서 정상적으로 작동해야합니다. –

+0

인터넷 제어 메시지 프로토콜 소켓은 호스트와 데이터를주고받는 데 사용되지 않으며 호스트에 짧은 제어 메시지를 보내기위한 용도로만 사용됩니다. 그것이 연결될 필요가없는 이유입니다. –

+0

그런데, 정상적인 UDP 대신 ICMP (실제로 데이터 전송에 사용되지 않아야하는)를 사용하려는 이유는 무엇입니까? –

답변

0

감사합니다. 내 솔루션은 내가 핑 패키지를 보낼 경우 그래서는 원하는 등, 수신 코드에서 판사를 추가입니다 에코 응답 (0을 입력 코드 0), 내가

if type != 0: 
    continue 

를 작성하고 당신은 또한 경우 요지로 쓸 수 있습니다 == my_ip : 이

을 계속할 것 같다되지 않은 부드러운 솔루션을

0

Q1이 있습니다 내가 로컬 호스트에 결합하여 잘 두 매개 변수와 IOCTL를 호출 할 수 있었다.클라이언트가 동일한 시스템에서 실행되고 있다고 가정하면 클라이언트가 "localhost"로 전송되는지 확인하십시오. 그렇지 않으면 서버가 패킷을 수신하지 않습니다. 클라이언트가 다른 시스템에있는 경우 서버가 패킷을 수신하지 않습니다.

Q2 : 패킷을 보내는 데 IOCTL이 필요하지 않습니다. 그냥 sendto()를 통해 보내십시오.

질문 : 두 개의 대답이 표시되는 이유는 커널이 사용자 공간 코드 외에도 에코 요청을 처리하고 있기 때문입니다.

ICMP를 임의의 메시지 전달에 사용할 수 있지만 다른 사람이 지적한대로 의도 한 디자인이 아닙니다. 메시지 부분에서 데이터 부분이 잘 리게됩니다. 예를 들어, 에코 요청을 보낼 때 응답에는 보낸 모든 것이 포함됩니다. 그러나 유형 3 코드 3 인 응답에는 사용자 데이터가 포함되지 않고 ICMP 헤더의 처음 8 바이트 만 포함될 수 있습니다.