- UDP connect() and recv() on Linux
- 4 Answers 4
- Отправка и получение UDP-пакетов через Linux CLI
- Ожидания:
- Команда Netcat:
- Схема общей настройки:
- Отправить пакет UDP:
- Стартовый сервер:
- Стартовый клиент:
- Проверьте подключение:
- Отправлять UDP-пакеты:
- Проверяем пакеты в Wireshark:
- Другая команда для отправки пакетов UDP:
- Заключение:
- Рекомендации:
UDP connect() and recv() on Linux
If the socket sockfd is of type SOCK_DGRAM then serv_addr is the address to which datagrams are sent by default, and the only address from which datagrams are received. If the socket is of type SOCK_STREAM or SOCK_SEQPACKET, this call attempts to make a connection to the socket that is bound to the address specified by serv_addr.
I am trying to filter packets from two different multicast groups that are being broadcasted on the same port and I thought connect() would have done the job but I can’t make it work. In facts when I add it to my program I don’t receive any packet. More info in this thread. This is how I set the connect parameters:
memset(&mc_addr, 0, sizeof(mc_addr)); mc_addr.sin_family = AF_INET; mc_addr.sin_addr.s_addr = inet_addr(multicast_addr); mc_addr.sin_port = htons(multicast_port); printf("Connecting. \n"); if( connect(sd, (struct sockaddr*)&mc_addr, sizeof(mc_addr)) < 0 ) < perror("connect"); return -1; >printf("Receiving. \n"); while( (len = recv(sd, msg_buf, sizeof(msg_buf), 0)) > 0 ) printf("Received %d bytes\n", len);
4 Answers 4
Your program (probably) has the following problems:
- you should be using bind() instead of connect(), and
- you’re missing setsockopt(. IP_ADD_MEMBERSHIP, . ).
Here’s an example program that receives multicasts. It uses recvfrom(), not recv(), but it’s the same except you also get the source address for each received packet.
To receive from multiple multicast groups, you have three options.
First option: Use a separate socket for each multicast group, and bind() each socket to a multicast address. This is the simplest option.
Second option: Use a separate socket for each multicast group, bind() each socket INADDR_ANY, and use a socket filter to filter out all but a single multicast group.
Because you’ve bound to INADDR_ANY, you may still get packets for other multicast groups. It is possible to filter them out using the kernel’s socket filters:
#include #include #include #include /** * Adds a Linux socket filter to a socket so that only IP * packets with the given destination IP address will pass. * dst_addr is in network byte order. */ int add_ip_dst_filter (int fd, uint32_t dst_addr) < uint16_t hi = ntohl(dst_addr) >> 16; uint16_t lo = ntohl(dst_addr) & 0xFFFF; struct sock_filter filter[] = < BPF_STMT(BPF_LD + BPF_H + BPF_ABS, SKF_NET_OFF + 16), // A ; struct sock_fprog fprog = < .len = sizeof(filter) / sizeof(filter[0]), .filter = filter >; return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); >
Third option: use a single socket to receive multicasts for all multicast groups.
In that case, you should do an IP_ADD_MEMBERSHIP for each of the groups. This way you get all packets on a single socket.
However, you need extra code to determine which multicast group a received packet was addressed to. To do that, you have to:
- receive packets with recvmsg() and read the IP_PKTINFO or equivalent ancillary data message. However, to make recvmsg() give you this message, you first have to
- enable reception of IP_PKTINFO ancillary data messages with setsockopt().
The exact thing you need to do depends on IP protocol version and OS. Here’s how I did it (IPv6 code not tested): enabling PKTINFO and reading the option.
Here’s a simple program that receives multicasts, which demonstrates the first option (bind to multicast address).
#include #include #include #include #include #define MAXBUFSIZE 65536 int main (int argc, char **argv) < if (argc != 4) < printf("Usage: %s \n", argv[0]); return 1; > int sock, status, socklen; char buffer[MAXBUFSIZE+1]; struct sockaddr_in saddr; struct ip_mreq imreq; // set content of struct saddr and imreq to zero memset(&saddr, 0, sizeof(struct sockaddr_in)); memset(&imreq, 0, sizeof(struct ip_mreq)); // open a UDP socket sock = socket(PF_INET, SOCK_DGRAM, 0); if (sock < 0) < perror("socket failed!"); return 1; >// join group imreq.imr_multiaddr.s_addr = inet_addr(argv[1]); imreq.imr_interface.s_addr = inet_addr(argv[3]); status = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&imreq, sizeof(struct ip_mreq)); saddr.sin_family = PF_INET; saddr.sin_port = htons(atoi(argv[2])); saddr.sin_addr.s_addr = inet_addr(argv[1]); status = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)); if (status < 0) < perror("bind failed!"); return 1; >// receive packets from socket while (1) < socklen = sizeof(saddr); status = recvfrom(sock, buffer, MAXBUFSIZE, 0, (struct sockaddr *)&saddr, &socklen); if (status < 0) < printf("recvfrom failed!\n"); return 1; >buffer[status] = '\0'; printf("Received: '%s'\n", buffer); > >
Отправка и получение UDP-пакетов через Linux CLI
Мы уже знаем о двух основных протоколах транспортного уровня, таких как TCP и UDP. Для получения дополнительной информации о TCP и UDP вы можете проверить справочный раздел. В этой статье мы узнаем, как отправлять и получать UDP-пакеты через интерфейс командной строки (CLI) Linux, используя NC (в основном) команда.
Ожидания:
Вот основные моменты, которые следует изучить из этой статьи
- Понимать NC команда в Linux.
- Использовать NC команда для отправки и получения UDP-пакетов по сети.
- Отправьте несколько удобочитаемых предложений через NC команда.
- Захватить пакет UDP, отправленный NC команда.
- Проверить сетевой пакет в Wireshark.
- Найдите любую другую команду, кроме netcat для Linux.
Команда Netcat:
Команда Netcat (nc) по умолчанию установлена в ОС Linux. Откройте один терминал [сочетание клавиш Alt + Ctrl + t] и используйте команду ниже, чтобы проверить, присутствует ли NC или нет.
Это nc из пакета netcat-openbsd. Доступен альтернативный NC
в традиционном пакете netcat.
использование: nc [-46bCDdhjklnrStUuvZz] [-I длина] [-i интервал] [-O длина]
[-P proxy_username] [-p source_port] [-q секунды] [-s source]
[-T toskeyword] [-V rtable] [-w timeout] [-X proxy_protocol]
[-x proxy_address [: порт]] [пункт назначения] [порт]
Это означает, что команда nc уже существует в Linux.
Схема общей настройки:
Отправить пакет UDP:
Давайте возьмем пример, как мы отправим пакет UDP из системы A в систему B. Итак, в концепции сервер-клиент мы должны запустить сервер на стороне системы B и клиент на стороне системы A.
Также у нас есть действующие IP-адреса.
Система А IP: 192.168.1.6
Система B IP: 192.168.1.102
Стартовый сервер:
Чтобы запустить сервер с помощью команды nc, используйте команду ниже в терминале системы B
На данный момент у этой команды нет выходных данных для отображения. Это просто режим прослушивания порта 9999.
Стартовый клиент:
Чтобы подключиться к серверу с помощью команды nc, используйте команду ниже в терминале системы A
Теперь система A должна подключиться к системе B. Итак, мы предоставили IP-адрес сервера и номер порта.
Проверьте подключение:
Мы можем проверить приведенную ниже команду для подтверждения о подключении клиента к порту сервера.
Отправлять UDP-пакеты:
Теперь мы можем отправить пакет udp из системы A в систему B и наоборот.
Теперь перейдите в систему A и отправьте любые предложения вроде
«Привет, я из LinuxHint [Система A 192.168.1.6] »
Мы должны увидеть это на стороне Системы B. Вот скриншот
Мы также можем отправлять UDP-пакеты из Системы B в Систему A.
Перейдите в систему B и отправьте предложение вроде
«Привет, я из LinuxHint [Система B 192.168.1.102] «
Вот скриншот из Системы B
Вот скриншот из Системы А
Проверяем пакеты в Wireshark:
Теперь, когда мы отправляем UDP-пакеты из системы A в систему B и наоборот, мы можем запустить Wireshark либо в системе A, либо в системе B. Здесь у нас есть файл захвата, давайте проведем некоторый анализ и подтвердим, использует ли этот сервер и клиент для связи протокол UDP.
Обратите внимание, что мы проанализируем только первое сообщение:
Система A отправила:
«Привет, я из LinuxHint [Система A 192.168.1.6] »
Мы будем использовать фильтр «UDP.порт == 9999 ” чтобы получить только связанные пакеты в Wireshark. См. Снимок экрана ниже для анализа захвата Wireshark:
Чтобы узнать, как использовать Wireshark, перейдите по ссылке ниже
https: // linuxhint.ru / wirehark_basics_how_to_use /
Другая команда для отправки пакетов UDP:
Есть еще один способ отправки UDP-пакетов
Запустите сервер в системе B:
Выполните команду ниже в системе A:
$ echo -n «привет»> / dev / udp / 192.168.1.102/8000
192.168.1.102: IP системы B
8000: порт сервера
Сообщение отправлено: «привет»
Но мы можем послать только один раз «привет». Если мы убьем сервер и перезапустим его, он заработает.
Заключение:
Из приведенного выше упражнения мы узнали механизм отправки некоторых сообщений по протоколу UDP. И лучший способ — использовать NC команда в Linux.
Рекомендации:
Чтобы понять TCP: https: // linuxhint.ru / tcp_packet_capture_analysis /
Чтобы понять UDP: https: // linuxhint.ru / udp_wireshark_analysis /
Игры
С каждым новым поколением видеокарт мы видим, как разработчики игр расширяют границы графической точности и приближаются на шаг ближе к фотореализму. .
Игры
Создание собственного транспортного симулятора может быть увлекательным, расслабляющим и чрезвычайно увлекательным занятием. Вот почему вам нужно попр.
Игры
OpenTTD — одна из самых популярных бизнес-симуляторов. В этой игре вам нужно создать замечательный транспортный бизнес. Тем не менее, вы начнете в нач.
Свежие статьи об операционных системах. Множество интересных гайдов и полезных советов. Почувствуйте себя своим в мире современных технологий