2014-12-18 2 views
0

나는 간단한 UDP 메시징 시스템에서 작업하고 있으며 대부분 작동하고 있습니다. 이 구조는 특정 포트에서 수신 대기하는 모든 클라이언트에게 메시지를 브로드 캐스트하는 서버 1 대를 가지고 있습니다 (LAN에 연결하거나 인터넷에 연결되지 않은 Ad-Hoc 네트워크에 연결하기 위해 테스트 용 PC가 현재 웹에 연결되어 있음). 내 문제는 내가 메시지를 보낼 때마다 클라이언트가 2 부를 받는다는 것이다. 현재 대상 IP를 서브넷으로 설정하지 않으므로 이것이 문제 일 수 있습니다.하나의 수신에 대해 여러 수신 메시지 받기

(참고 : "클라이언트"가 바인딩되어 있기 때문에 표준 클라이언트 - 서버 용어를 위반합니다. 특정 항구,하지만 나와 함께 곰). 포트는 클라이언트가 반복적으로 읽어 스레드를 생성합니다 연 후

d_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 

    //Set port so that calls to recvfrom do not block. Instead recvfrom returns an error if no data is present now. 
    u_long l_no_block_specifier = 1; 
    int l_socket_control_result = ioctlsocket(d_socket, 
              FIONBIO, 
              &l_no_block_specifier); 

    if(d_socket == -1) 
    { 
     printf("\nError in creating socket"); 
     return false; 
    } 

    //Zero out the broadcast address member to initialize it 
    memset(&d_server_address, 
      0, 
      sizeof(d_server_address)); 

    //Specify that 
    d_server_address.sin_family = AF_INET; 
    d_server_address.sin_port = htons(34444); 
    d_server_address.sin_addr.s_addr = INADDR_ANY; 

    d_address_length = sizeof(d_server_address); 

    //Bind socket and print an error if bind fails. 
    if (bind(d_socket, (SOCKADDR*)&d_server_address, sizeof(SOCKADDR_IN)) != 0) 
    { 
     printf("\nError in binding socket"); 
    } 

:

d_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 

    if(d_socket == -1) 
    { 
     printf("\nError in creating socket"); 
     return false; 
    } 

    //socket option set to 1 because we are setting the SO_BROADCAST setting to true 
    //MSDN says to use int for boolean option types. 
    int l_socket_option = 1; 

    setsockopt(d_socket, 
       SOL_SOCKET, 
       SO_BROADCAST, 
       (char*)&l_socket_option, 
       sizeof(int)); 

    //Zero out the broadcast address member to initialize it 
    memset(&d_broadcast_address, 
      0, 
      sizeof(d_broadcast_address)); 

    //Specify that 
    d_broadcast_address.sin_family = AF_INET; 
    d_broadcast_address.sin_port = htons(34444); 
    d_broadcast_address.sin_addr.s_addr = INADDR_BROADCAST; 

내 클라이언트가 포트과 같이 열립니다 : 그래서 여기

내 서버가 대상 데이터를 지정하는 방법입니다 항구. 필자는 메시지의 순서를 나타내는 모든 정수를 전송하는 작은 테스트 응용 프로그램을 작성했습니다. 이 프로그램의 출력은 다음과 같습니다 : 나는 꽤 그것을 철저하게 테스트 (프로그램 자체가 실수 각 메시지에 대해이 통지를 인쇄되지 않는다는 것을 확신했습니다

Sending message #0 at time = 4.0 
Got message #0 at time = 4.0 
Got message #0 at time = 25.0 
Sending message #1 at time = 1004.0 
Got message #1 at time = 1004.0 
Got message #1 at time = 1047.0 
Got message #2 at time = 2004.0 
Sending message #2 at time = 2004.0 
Got message #2 at time = 2064.0 
Sending message #3 at time = 3005.0 
Got message #3 at time = 3005.0 
Got message #3 at time = 3086.0 

타임 스탬프 쇼 외에 2 개의 영수증 사이의 뒤늦은 도착).

왜 이런 일이 발생합니까? 내 테스트 PC가 인터넷에 연결되어있어 브로드 캐스트 때문에 메시지가 내 자신의 PC로 되돌아 오는 2 개의 다른 경로를 통해 라우팅되기 때문에 이것이 원인이라고 추측합니다.

는 편집 :이 INADDR_ANY를 지정하는 대신 자신의 IP 주소를 사용하여 방송 포트를 결합하여이 중복 영수증을 중지하도록

나는 클라이언트를 변경했습니다. 또한 서버가 부분적으로 서브넷에서만 브로드 캐스팅되도록 업데이트했지만 여러 수신 확인에 영향을 미쳤다고 생각하지 않습니다.

+0

당신은 실제 송신 또는 읽기 코드를 보여주지 않았지만, 특정 서브넷 브로드 캐스트 주소 대신에 'INADDR_BROADCAST' (255.255.255.255)로 보내고 있기 때문에 수신기를 INADDR_ANY '(0.0.0.0)을 사용하는 경우 수신기의 다른 NIC에서 각 메시지의 복사본을 여러 번받을 가능성이 있습니다. 각 NIC를 실제로 수신하는 NIC를 결정하려면'recvfrom() '대신 ['WSARecvMsg()'] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms741687.aspx)를 사용할 수 있습니다 패킷. –

+0

그래, 내가 보낸/받기 코드를 붙여 넣지 않았어. 내가 ipconfig를 할 때 "이더넷 어댑터 로컬 영역 연결"에서 2 개의 IP 주소와 "무선 LAN 어댑터 무선 네트워크 연결"에서 하나를 볼 수 있습니다. 그래서 나는 여분의 메시지가 메시지에 대한 내 컴퓨터에 2 개의 IP 대상을 가지고 있다는 사실에서 비롯된 것이라고 생각합니다. – Ian

답변

0

클라이언트를 변경하여 INADDR_ANY를 지정하는 대신 자체 IP 주소를 사용하여 브로드 캐스트 포트를 바인딩하고 이로 인해 중복 확인이 중지되었습니다. 또한 서버가 부분적으로 서브넷에서만 브로드 캐스팅되도록 업데이트했지만 여러 수신 확인에 영향을 미쳤다고 생각하지 않습니다. - Ian

관련 문제