boost多网卡udp组播绑定网卡发送

多网卡组播的时候,发送端要遍历本地ip进行发送。

sender.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
32
33
#pragma once
//
// sender.h
// udp组播发送类
//
#include <iostream>
#include <sstream>
#include <string>
#include <boost/asio.hpp>
#include "sender.h"

class multicast_sender
{
public:
multicast_sender(boost::asio::io_context& io_context
, const boost::asio::ip::address& multicast_address
, const unsigned short multicast_port
, const boost::asio::ip::udp::endpoint& bind_endpoint);
~multicast_sender();
// 异步发送,没发送完之前不能修改data
void async_send_to(const std::vector<char>& data
, std::function<void (boost::system::error_code ec, std::size_t)> handler);
void async_send_to(const char* data, size_t length
, std::function<void(boost::system::error_code ec, std::size_t)> handler);
void async_send_to(const std::string& data
, std::function<void(boost::system::error_code ec, std::size_t)> handler);

private:
multicast_sender(const multicast_sender&) = delete;
struct multicast_sender_impl;
multicast_sender_impl* impl{ nullptr };
};

sender.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
#include "sender.h"

struct multicast_sender::multicast_sender_impl {
boost::asio::io_context& io_context_;
boost::asio::ip::udp::endpoint endpoint_;
boost::asio::ip::udp::socket socket_;
std::string message_;
multicast_sender_impl(boost::asio::io_context& io_context
, const boost::asio::ip::address& multicast_address
, const unsigned short multicast_port
, const boost::asio::ip::udp::endpoint& bind_endpoint)
: io_context_(io_context)
, socket_(io_context, endpoint_.protocol())
, endpoint_(multicast_address, multicast_port)
{
socket_.bind(bind_endpoint);
}
};

multicast_sender::multicast_sender(boost::asio::io_context& io_context
, const boost::asio::ip::address& multicast_address
, const unsigned short multicast_port
, const boost::asio::ip::udp::endpoint& bind_endpoint)
{
impl = new multicast_sender_impl(io_context, multicast_address, multicast_port, bind_endpoint);
}

multicast_sender::~multicast_sender()
{
delete impl;
}


void multicast_sender::async_send_to(const std::vector<char>& data
, std::function<void(boost::system::error_code ec, std::size_t)> handler)
{
impl->socket_.async_send_to(
boost::asio::buffer(data, data.size()), impl->endpoint_,
handler);
}

void multicast_sender::async_send_to(const char* data, size_t length
, std::function<void(boost::system::error_code ec, std::size_t)> handler)
{
impl->socket_.async_send_to(
boost::asio::buffer(data, length), impl->endpoint_
, handler);
}

void multicast_sender::async_send_to(const std::string& data
, std::function<void(boost::system::error_code ec, std::size_t)> handler)
{
impl->message_ = data;
impl->socket_.async_send_to(
boost::asio::buffer(impl->message_), impl->endpoint_
, handler);
}

test_sender.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
#include "sender.h"
#include <thread>
#include <iostream>

void handler1(boost::system::error_code ec, std::size_t length)
{
if (!ec)
{
std::cout << "send ok!" << std::endl;
}
else
{
std::cout << "send error! message: " << ec.message() << std::endl;
}
}

int main(int argc, char* argv[])
{
try
{
// 多网卡时要绑定网卡地址。0.0.0.0会选择第一块网卡发送UDP包
auto listen_address = boost::asio::ip::make_address("192.168.31.111");
auto multicast_address = boost::asio::ip::make_address("239.1.2.3");
constexpr unsigned short multicast_port = 30001;
boost::asio::io_context io_context;
boost::asio::io_context::work work(io_context);
boost::asio::ip::udp::endpoint bind_endpoint(boost::asio::ip::make_address("192.168.31.111"), 0);

multicast_sender sender(io_context
, multicast_address
, multicast_port
, bind_endpoint);

std::thread t(
[&sender, &work]() {
std::string message;
for (int i = 0; i < 10; ++i)
{
message = "message: " + std::to_string(i);
sender.async_send_to(message, handler1);
std::this_thread::sleep_for(std::chrono::seconds(1));
}
work.get_io_context().stop();
}
);
io_context.run();
if (t.joinable())
t.join();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}

return 0;
}

gitee

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