C ++ UDP Broadcast с использованием :: write - PullRequest
0 голосов
/ 30 мая 2018

Я пишу клиент-серверное приложение UDP.Сервер - это широковещательный сервер, который транслирует по определенному порту двум клиентам в одной подсети.Каждый клиент получает дейтаграмму и отправляет ответ на сервер.Каждый клиент заранее знает ip-адрес сервера.

Мой клиент в основном такой же, как в примере клиента http://man7.org/linux/man-pages/man3/getaddrinfo.3.html,, т.е. он использует функцию connect () для указания конечной точки всех исходящих пакетов.,Используя подключенный UDP, клиент может использовать read () и write () для дескриптора файла сокета, а не sendto / recvfrom.

Для моего сервера я хочу принять аналогичный подход - настроить сокет для широковещательной передачи.и вызвать read / write для дескриптора файла.Я могу связать () сокет для прослушивания входящих дейтаграмм на указанном порту, и они прекрасно собираются.

За исключением проверки ошибок, мой код сервера выглядит так:

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

int broadcast = 1;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof int);

struct sockaddr_in servaddr;
memset((char*) &servaddr, 0, sizeof servaddr);
servaddr.sin_family = AF_INET;
servaddr.sin_port   = htons(PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

int success = bind(sockfd, (struct sockaddr*) &servaddr, sizeof servaddr);

int BUFSIZE = 256;
char buf[BUFSIZE];

while (1)
{
    // this works fine
    int bytes_read = read(sockfd, buf, BUFSIZE);

    // WANT TO BROADCAST HERE
    int bytes_written = write(sockfd, buf, bytes_read); 
}

ОднакоКогда я пытаюсь передать пакет в строке write (), я получаю сообщение об ошибке «Адрес получателя не указан».Я мог бы вызвать connect (), чтобы установить адрес назначения, но я не думаю, что connect () работает с широковещательным сокетом.

Есть ли способ вещания с использованием write (), а не sendto?

1 Ответ

0 голосов
/ 30 мая 2018

Проблема с использованием connect () для широковещательной рассылки заключается в том, что (помимо изменения поведения send () / write ()), connect () установит фильтр на сокет, чтобы он принимал только пакеты, чьи исходныеПоле IP соответствует IP-адресу, указанному в аргументе для connect ().

Это означает, что если вы вызовите connect () для вашего сокета с широковещательным адресом в качестве аргумента, то ваш сокет будет принимать только пакеты, поступающие отэтот широковещательный адрес - но пакеты (AFAIK) никогда не помечаются как поступающие с широковещательного адреса - скорее, их поле Source-IP установлено на IP-адрес компьютера, который отправил пакет, как обычно.В результате, если вы подключите () свой сокет к широковещательному адресу, вы не получите никаких пакетов на этом сокете.

...