2014-12-18 3 views
0

Я работаю над простой системой обмена сообщениями UDP, и у меня это работает в основном. Структура состоит в том, чтобы иметь 1 сервер, который просто передает сообщения всем клиентам, которые прослушивают определенный порт (его просто для использования в локальной сети или специальной сети, не подключенной к Интернету, хотя мой тестовый компьютер в настоящее время подключен к сети). Моя проблема в том, что каждый раз, когда я отправляю сообщение, клиент получает 2 копии. На данный момент я не устанавливаю целевой IP в качестве подсети, поэтому, возможно, это проблема:Получение нескольких входящих сообщений для одной отправки

(Примечание: Я знаю, что нарушаю стандартную терминологию клиент-сервер, потому что мой «клиент» является обязательным конкретный порт, но неся со мной).

Так вот как мой сервер определяет целевой данные: открывает

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; 

Моего клиента порт так:

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"); 
    } 

После того, как порты открыты клиент порождает нить повторно считывает порт. Я написал небольшое тестовое приложение, которое просто отправляет целое число, представляющее последовательность сообщения. Выход этой программы, как показано ниже:

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 уведомления для каждого сообщения (кроме временных меток шоу запоздалое прибытие между двумя квитанциями).

Почему это происходит? Я предполагаю, что это связано с тем, что мой тестовый компьютер подключен к Интернету, и поэтому сообщение передается через два разных пути обратно на мой собственный компьютер из-за широковещательной передачи.

EDIT:

Я изменил клиент так, что он связывает порт вещания, используя свой собственный IP-адрес вместо указания INADDR_ANY и это прекратилось дубликат квитанции. Я также обновил сервер для трансляции только в подсети, частью которой он является, но я не думаю, что это повлияло на несколько квитанций.

+0

Вы не указали свой фактический код отправки или чтения, но я бы предположил, что, поскольку вы отправляете в INADDR_BROADCAST (255.255.255.255) вместо определенного широковещательного адреса подсети и привязываете ресивер к 'INADDR_ANY '(0.0.0.0) вместо конкретного сетевого адаптера, скорее всего, вы получаете несколько копий каждого сообщения от разных сетевых адаптеров на приемнике. Вы можете использовать ['WSARecvMsg()'] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms741687.aspx) вместо 'recvfrom()', чтобы определить, какая сетевая карта фактически получает каждый пакет. –

+0

Да, я не вставлял код отправки/получения, потому что это было бы очень много. Когда я делаю ipconfig, я вижу, что у меня есть 2 IP-адреса, 1 из «Подключение локальной сети Ethernet-адаптера», а другой - от «Беспроводное сетевое подключение беспроводной сети». Поэтому я предполагаю, что дополнительное сообщение исходит из того, что у меня есть 2 цели IP на моей машине, чтобы сообщение попало? – Ian

ответ

0

Я изменил клиент так, чтобы он связывал широковещательный порт с использованием собственного IP-адреса вместо указания INADDR_ANY, и это остановило дубликаты квитанций. Я также обновил сервер для трансляции только в подсети, частью которой он является, но я не думаю, что это повлияло на несколько квитанций. - Ian

Смежные вопросы