gpt4 book ai didi

c++ - 如何接收来自已订阅组的组播数据包?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:10:29 24 4
gpt4 key购买 nike

在我的 ubuntu 16.04 系统中,我运行了以下程序:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>


#define HELLO_PORT 12345
#define HELLO_GROUP "225.0.0.37"
#define MSGBUFSIZE 256

main(int argc, char *argv[])
{
struct sockaddr_in addr;
int fd, nbytes,addrlen;
struct ip_mreq mreq;
char msgbuf[MSGBUFSIZE];

u_int yes=1;

if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
perror("socket");
exit(1);
}

if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
perror("Reusing ADDR failed");
exit(1);
}

memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(HELLO_GROUP);
addr.sin_port=htons(HELLO_PORT);

/* bind to receive address */
if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
perror("bind");
exit(1);
}

mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
mreq.imr_interface.s_addr=htonl(INADDR_ANY);
if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
perror("setsockopt");
exit(1);
}
}

这个程序只是订阅我的系统以接收来自组 225.0.0.37 的组播 UDP 数据包

在我本地网络的另一个系统上,我有另一个程序定期向这个组发送数据包

在使用上述程序订阅群组后,我确认我正在从 wireshark 获取发往 225.0.0.37 的 UDP 数据包

我想通过另一个程序读取这些传入的数据包。而且我不想使用原始套接字。以下是我编写的另一个程序:

#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/lexical_cast.hpp>

using boost::asio::ip::udp;

static const int max_length = 1024;

char data_[max_length];

void handle_receive_from(const boost::system::error_code& error, size_t bytes_recvd)
{
std::cout.write(data_, bytes_recvd);
}

int main(int argc, char* argv[])
{
try
{

boost::asio::io_service io_service;

udp::endpoint local_endpoint = boost::asio::ip::udp::endpoint(
boost::asio::ip::address::from_string("225.0.0.37"), boost::lexical_cast<int>("12345"));
std::cout << "Bind " << local_endpoint << std::endl;

udp::socket socket(io_service);
socket.open(local_endpoint.protocol());
socket.set_option(udp::socket::reuse_address(true));
socket.bind(local_endpoint);

socket.async_receive(
boost::asio::buffer(data_, max_length),
boost::bind(&handle_receive_from,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));

io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}

即使我看到数据包通过 wireshark,该程序也没有获取任何数据。我究竟做错了什么?甚至可以获取数据吗?总体问题是这样的:我可以在一个程序中订阅多播组并在另一个程序中接收数据包吗?

最佳答案

这取决于。

如果您的第一个程序很快退出,那么 os 将关闭套接字,发送 IGMP 离开,这样您的第二个程序就不会收到任何多播数据包。所以你应该保持第一个程序运行(添加一个函数来永远阻塞),这样它就不会离开多播组。

Linux 内核实际上跟踪每个套接字的组成员资格,似乎它不使用它来过滤多播数据包。因此,您可以在一个程序中订阅多播组并在另一个程序中接收数据包,直到取消订阅(适用于我的 Ubuntu 14.04)。不确定这个策略是否会改变,但在我的 OS X 10.10 上,它不允许这样的事情。

关于c++ - 如何接收来自已订阅组的组播数据包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42385765/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com