Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
⊗cpSpUdSev 686 of 696 menu
◀ ▶

Несколько UDP-пакетов в C++

Серия датаграмм на одном сокете обрабатывается в цикле с конечным счетчиком.

После каждого recvfrom тот же буфер и адрес отправителя используют снова. На отправке цикл вызывает sendto для каждой строки - порядок на проводе обычно совпадает с порядком вызовов на localhost. Приемник в потоке читает две датаграммы и печатает каждую, отправитель шлет их на 127.0.0.1:

#include <arpa/inet.h> #include <atomic> #include <cstring> #include <iostream> #include <netinet/in.h> #include <string> #include <sys/socket.h> #include <thread> #include <unistd.h> int main() { std::atomic<bool> ready{false}; std::thread receiver([&]() { int recv_fd = socket(AF_INET, SOCK_DGRAM, 0); if (recv_fd == -1) { return; } sockaddr_in local{}; local.sin_family = AF_INET; local.sin_port = htons(18081); if (inet_pton(AF_INET, "127.0.0.1", &local.sin_addr) != 1 || bind( recv_fd, reinterpret_cast<sockaddr*>(&local), sizeof(local) ) == -1) { close(recv_fd); return; } ready.store(true, std::memory_order_release); for (int i = 0; i < 2; ++i) { char buf[256]; sockaddr_in peer{}; socklen_t peer_len = sizeof(peer); ssize_t n = recvfrom( recv_fd, buf, sizeof(buf), 0, reinterpret_cast<sockaddr*>(&peer), &peer_len ); if (n > 0) { std::string text(buf, static_cast<size_t>(n)); std::cout << text << "\n"; } } close(recv_fd); }); while (!ready.load(std::memory_order_acquire)) { } int send_fd = socket(AF_INET, SOCK_DGRAM, 0); if (send_fd == -1) { receiver.join(); return 1; } sockaddr_in dest{}; dest.sin_family = AF_INET; dest.sin_port = htons(18081); if (inet_pton(AF_INET, "127.0.0.1", &dest.sin_addr) != 1) { close(send_fd); receiver.join(); return 1; } const char* words[] = {"one", "two"}; for (const char* word : words) { if (sendto( send_fd, word, std::strlen(word), 0, reinterpret_cast<sockaddr*>(&dest), sizeof(dest) ) == -1) { close(send_fd); receiver.join(); return 1; } } close(send_fd); receiver.join(); return 0; }

Ответ на каждый пакет тоже можно слать в цикле на адрес из соответствующего приема. Отправитель тогда читает несколько ответов подряд:

#include <arpa/inet.h> #include <atomic> #include <cstring> #include <iostream> #include <netinet/in.h> #include <string> #include <sys/socket.h> #include <thread> #include <unistd.h> int main() { std::atomic<bool> ready{false}; std::thread receiver([&]() { int recv_fd = socket(AF_INET, SOCK_DGRAM, 0); if (recv_fd == -1) { return; } sockaddr_in local{}; local.sin_family = AF_INET; local.sin_port = htons(18081); if (inet_pton(AF_INET, "127.0.0.1", &local.sin_addr) != 1 || bind( recv_fd, reinterpret_cast<sockaddr*>(&local), sizeof(local) ) == -1) { close(recv_fd); return; } ready.store(true, std::memory_order_release); for (int i = 0; i < 2; ++i) { char buf[256]; sockaddr_in peer{}; socklen_t peer_len = sizeof(peer); ssize_t n = recvfrom( recv_fd, buf, sizeof(buf), 0, reinterpret_cast<sockaddr*>(&peer), &peer_len ); if (n > 0) { std::string tag(buf, static_cast<size_t>(n)); std::string reply = "echo " + tag; sendto( recv_fd, reply.c_str(), reply.size(), 0, reinterpret_cast<sockaddr*>(&peer), peer_len ); } } close(recv_fd); }); while (!ready.load(std::memory_order_acquire)) { } int send_fd = socket(AF_INET, SOCK_DGRAM, 0); if (send_fd == -1) { receiver.join(); return 1; } sockaddr_in dest{}; dest.sin_family = AF_INET; dest.sin_port = htons(18081); if (inet_pton(AF_INET, "127.0.0.1", &dest.sin_addr) != 1) { close(send_fd); receiver.join(); return 1; } const char* words[] = {"a", "b"}; for (const char* word : words) { if (sendto( send_fd, word, std::strlen(word), 0, reinterpret_cast<sockaddr*>(&dest), sizeof(dest) ) == -1) { close(send_fd); receiver.join(); return 1; } } for (int i = 0; i < 2; ++i) { char ans_buf[256]; sockaddr_in from{}; socklen_t from_len = sizeof(from); ssize_t ans_n = recvfrom( send_fd, ans_buf, sizeof(ans_buf), 0, reinterpret_cast<sockaddr*>(&from), &from_len ); if (ans_n > 0) { std::string answer(ans_buf, static_cast<size_t>(ans_n)); std::cout << answer << "\n"; } } close(send_fd); receiver.join(); return 0; }

Отправьте пять пакетов с текстами "n1" … "n5". Приемник выведет пять строк по одной на пакет.

Примите три запроса и на каждый ответьте "ok". Отправитель выведет три строки ответа.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить