2012-04-02 3 views
2

내 응용 프로그램이 내 서버에있는 모든 인터페이스의 패킷을 수신 대기하도록 INADDR_ANY에 바인딩 된 UDP 소켓을 열었습니다. 나는 같은 소켓을 통해 응답을 보내고있다.INADDR_ANY와 UDP 연결을위한 기본 소스 IP 변경

그러나 서버로부터 답장을 보내는 동안, 나가는 데 필요한 인터페이스에 따라 linux의 IP 레이어가 기본 IP를 선택합니다. 이 인터페이스와 관련된 IP는이 UDP 서버가 클라이언트로부터 쿼리를받은 대상 주소가 아닐 수도 있습니다. 따라서 서버로부터의 응답의 소스 IP는 질의가 제공된 목적지 IP와 다르다. 클라이언트는 그러한 회신에 불편할 수 있습니다. http://www.cs.cmu.edu/~srini/15-441/F01.full/www/assignments/P2/htmlsim_split/node18.html

가 어떻게이 기본 동작을 변경하고 소스 주소의 특정 인터페이스 IP를 사용할 수 있습니다 링크를

은 UDP와 INADDR_ANY의 동작을 준다? 이는 소스 코드가 무엇인지 결정하기 위해 응용 프로그램 코드를보다 잘 제어합니다. 또한 응답의 소스 주소가 쿼리가 제공된 대상 주소와 동일해야합니다.

+0

조금 더 많은 작업이 수행되지만 원시 소켓을 사용하지 않을 생각이십니까? 그런 다음 IP 및 UDP 헤더의 모든 필드를 원하는대로 변경할 수 있습니다. –

+0

@JoachimPileborg 여기에 원시 소켓을 사용하지 않는 것이 좋습니다. 기본적으로 응용 프로그램에서 UDP를 다시 구현하고, 커널 지식없이 사용할 UDP 포트를 선택하고 (자체 선택을 방해 할 수 있음) 루트 액세스가 필요합니다. – Celada

+0

거기에는 어떤 인터페이스 UDP가 서버 소스 주소로 선택되는지 말할 수있는 방법이 없습니까? – superbCoder

답변

1

의 인터페이스가 여러 개 있다고 가정하면 (그중 하나가 올바른 ip를 가짐) 나가는 응답을 위해 인터페이스에 바인딩 할 수 있습니다. SO_BINDTODEVICE 소켓 옵션을 살펴보십시오.

int bind_sock2inf(int sock, char *interface_name) 
{ 
    int status = -1; 
    struct ifreq ifr; 

    memset(&ifr, 0, sizeof(ifr)); 
    snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), interface_name); 
    if ((status = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, 
       (void *)&ifr, sizeof(ifr))) < 0) { 
     log_debug(4, "Failed binding to interface named %s", inf_name); 
    } 
    else log_debug(3, "Binding to interface %s", inf_name); 

    return status; 
} 

이제 발신 요청은이 인터페이스에 연결된 IP 주소를 자동으로 사용해야합니다. 유일한 단점은이 소켓의 다른 인터페이스에서 메시지 수신을 중단한다는 것입니다.

가능한 작업 방법은 다음과 같습니다

  1. 어떤 인터페이스 및 전송하기 전에 무엇을해야 인터페이스로 전송하고 바인드 또 다른 하나에 결합되지 않은 청취를위한 별도의 소켓을 사용합니다.

  2. 메시지를 보내기 전에 인터페이스에 바인딩하고 다시 바인딩하여 전송 직후 이전 바인드를 지 웁니다. 그러나이 시간 프레임 동안 수신 된 모든 패킷은 소켓에 연결되어 인터페이스가 eth0이고 패킷이 eth1에 도착했습니다.

발신 패킷에 원본 ip를 연결하는데도 bind()을 간단히 사용할 수 있습니다.

관련 문제