boost多网卡udp组播绑定网卡接收

receiver.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#pragma once
//
// receiver.cpp
// udp组播接收类
//
#include <array>
#include <iostream>
#include <string>
#include <functional>
#include <boost/asio.hpp>

class multicast_receiver
{
public:
multicast_receiver(boost::asio::io_context& io_context
, const boost::asio::ip::address& listen_address
, const unsigned short& multicast_port
, const boost::asio::ip::address& multicast_address
, std::function<void (boost::system::error_code& ec
, const char* data, std::size_t length
, const boost::asio::ip::udp::endpoint& sender_endpoint)> receiver
, size_t buffer_max = 1024
);
~multicast_receiver();

private:
void do_receive();
multicast_receiver(const multicast_receiver&) = delete;
struct multicast_receiver_impl;
multicast_receiver_impl* impl{ nullptr };
};

receiver.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// CMakeProject.cpp: 定义应用程序的入口点。
//

#include "receiver.h"

struct multicast_receiver::multicast_receiver_impl
{
boost::asio::ip::udp::socket socket_;
boost::asio::ip::udp::endpoint sender_endpoint_;
std::function<void(boost::system::error_code& ec
, const char* data, std::size_t length
, const boost::asio::ip::udp::endpoint& sender_endpoint)> receiver_;
std::vector<char> data_;
multicast_receiver_impl(boost::asio::io_context& io_context,
std::function<void(boost::system::error_code& ec
, const char* data, std::size_t length
, const boost::asio::ip::udp::endpoint& sender_endpoint)> receiver
, size_t buffer_max)
: socket_(io_context)
, receiver_(receiver)
{
data_.resize(buffer_max);
}
};

multicast_receiver::multicast_receiver(boost::asio::io_context& io_context
, const boost::asio::ip::address& listen_address
, const unsigned short& multicast_port
, const boost::asio::ip::address& multicast_address
, std::function<void(boost::system::error_code& ec
, const char* data, std::size_t length
, const boost::asio::ip::udp::endpoint& sender_endpoint)> receiver
, size_t buffer_max
)
{
impl = new multicast_receiver_impl(io_context, receiver, buffer_max);
// Create the socket so that multiple may be bound to the same address.
boost::asio::ip::udp::endpoint listen_endpoint(
listen_address, multicast_port);
impl->socket_.open(listen_endpoint.protocol());
impl->socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
impl->socket_.bind(listen_endpoint);

// Join the multicast group.
impl->socket_.set_option(
boost::asio::ip::multicast::join_group(multicast_address));

do_receive();
}

multicast_receiver::~multicast_receiver()
{
impl->socket_.cancel();
delete impl;
}


void multicast_receiver::do_receive()
{
impl->socket_.async_receive_from(
boost::asio::buffer(impl->data_), impl->sender_endpoint_,
[this](boost::system::error_code ec, std::size_t length)
{
if (impl->receiver_)
{
(impl->receiver_)(ec, impl->data_.data(), length, impl->sender_endpoint_);
}
if (!ec)
{
do_receive();
}
});
}

test_receiver.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "receiver.h"
#include <iostream>

void receiver_func(boost::system::error_code& ec
, const char* data, std::size_t length
, const boost::asio::ip::udp::endpoint& sender_endpoint)
{
if (!ec)
{
std::cout.write(data, length);
std::cout << std::endl;
}
}

int main(int argc, char* argv[])
{
try
{
boost::asio::io_context io_context;

auto listen_address = boost::asio::ip::make_address("192.168.31.111"); // 本地IP
auto multicast_address = boost::asio::ip::make_address("239.1.2.3");
constexpr unsigned short multicast_port = 30001;

multicast_receiver r(io_context
, listen_address
, multicast_port
, multicast_address
, receiver_func
);
io_context.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}

gitee

https://gitee.com/user.zt/boost-multicast