使用 Boost 的 UDP 通信(用于 MATLAB s-function)
UDP Communication using Boost (for MATLAB s-function)
我正在尝试为 UDP 通信创建一个 s-function(使用 C++ Boost 库)。
实施发件人非常简单,只需 15 分钟。我正在努力让接收器工作。
我在 Visual Studio 中创建了以下内容:
#define _WIN32_WINNT 0x0501
#define BOOST_ASIO_ENABLE_HANDLER_TRACKING
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <iostream>
#include <stdio.h>
typedef unsigned char UINT8;
typedef unsigned short UINT16;
using boost::asio::ip::udp;
using namespace std;
std::vector<char> receive_buffer;
void process_received_frame(const boost::system::error_code& error, size_t received_frame_size) {
if (error) {
cout << "Receive failed: " << error.message() << "\n";
return;
}
size_t ByteCount = 0;
std::cout << endl << "Received byte stream (Handler) [" << received_frame_size << "]: ";
for (std::vector<char>::const_iterator iter = receive_buffer.cbegin(); iter != receive_buffer.cend(); iter++)
{
ByteCount++;
printf("%02X ", (UINT8)*iter);
if (ByteCount == received_frame_size)
{
break;
}
}
std::cout << endl;
}
int main(int argc, char *argv[])
{
boost::asio::io_service io_service;
udp::socket socket(io_service);
udp::endpoint remote_endpoint = udp::endpoint(boost::asio::ip::address_v4::from_string("127.0.0.1"), 19001);
socket.open(udp::v4());
socket.bind(udp::endpoint(remote_endpoint));
receive_buffer.resize(255);
try
{
socket.async_receive_from(boost::asio::buffer(receive_buffer),
remote_endpoint,
boost::bind(&process_received_frame, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
catch (const std::exception& exp)
{
printf("%s\n", exp.what());
}
//io_service.poll();
io_service.run();
cout << "End";
std::cin.ignore();
}
我尝试从 Simulink 向 localhost:19001 发送 UDP,并且能够在 Visual Studio 中接收 UDP 数据包。处理程序 (process_received_frame) 被调用,一切似乎都正常工作,正如预期的那样。
但是,鉴于 io_service::run() 在阻塞模式下工作,如果端口 19001 上没有收到任何内容,它会暂停执行。所以我尝试使用 io_service::poll() (在代码中注释)以上)代替。但是,当我使用 poll() 时,它不会执行处理程序。如果我尝试从 main() 显示 'receive_buffer' 的内容,我会得到全 0。有趣的是,当我单步执行访问 'receive_buffer' 元素的代码时,我确实得到了正确的值。
不确定我做错了什么。很有可能是小学生的错误。
当我将其转换为 MATLAB-Simulink 的 s 函数时,它会做同样的事情 - 全为零。
如有任何帮助,我们将不胜感激。
干杯,
在您的处理程序函数中,您需要在处理完答案后最后调用 socket.async_receive_from
。 io_service.run()
returns 当没有更多处理程序在其处理队列中时。
请在此处查看 boost 文档中的示例:udp sync server example
编辑
重新阅读您的 question/comment,我不确定您的预期输出或行为是什么。
如果您只需要一个 UDP 帧,那么可以调用 io_service.run_one()
。
如果您不想run()
阻塞您的主线程,您需要启动另一个线程来调用run()
。类似于:
boost::asio::io_service io_service;
// Process handlers in a background thread.
boost::thread t(boost::bind(&io_service::run, &io_service));
...
io_service::run()
始终是阻塞调用。只能从当前调用 run()
的线程调用完成处理程序。 run()
进入 return 的唯一时间是当队列中没有更多处理程序时(您停止调用 async_receive
)或者如果您通过调用显式取消 run()
命令stop()
或 reset()
我正在尝试为 UDP 通信创建一个 s-function(使用 C++ Boost 库)。
实施发件人非常简单,只需 15 分钟。我正在努力让接收器工作。
我在 Visual Studio 中创建了以下内容:
#define _WIN32_WINNT 0x0501
#define BOOST_ASIO_ENABLE_HANDLER_TRACKING
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <iostream>
#include <stdio.h>
typedef unsigned char UINT8;
typedef unsigned short UINT16;
using boost::asio::ip::udp;
using namespace std;
std::vector<char> receive_buffer;
void process_received_frame(const boost::system::error_code& error, size_t received_frame_size) {
if (error) {
cout << "Receive failed: " << error.message() << "\n";
return;
}
size_t ByteCount = 0;
std::cout << endl << "Received byte stream (Handler) [" << received_frame_size << "]: ";
for (std::vector<char>::const_iterator iter = receive_buffer.cbegin(); iter != receive_buffer.cend(); iter++)
{
ByteCount++;
printf("%02X ", (UINT8)*iter);
if (ByteCount == received_frame_size)
{
break;
}
}
std::cout << endl;
}
int main(int argc, char *argv[])
{
boost::asio::io_service io_service;
udp::socket socket(io_service);
udp::endpoint remote_endpoint = udp::endpoint(boost::asio::ip::address_v4::from_string("127.0.0.1"), 19001);
socket.open(udp::v4());
socket.bind(udp::endpoint(remote_endpoint));
receive_buffer.resize(255);
try
{
socket.async_receive_from(boost::asio::buffer(receive_buffer),
remote_endpoint,
boost::bind(&process_received_frame, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
catch (const std::exception& exp)
{
printf("%s\n", exp.what());
}
//io_service.poll();
io_service.run();
cout << "End";
std::cin.ignore();
}
我尝试从 Simulink 向 localhost:19001 发送 UDP,并且能够在 Visual Studio 中接收 UDP 数据包。处理程序 (process_received_frame) 被调用,一切似乎都正常工作,正如预期的那样。
但是,鉴于 io_service::run() 在阻塞模式下工作,如果端口 19001 上没有收到任何内容,它会暂停执行。所以我尝试使用 io_service::poll() (在代码中注释)以上)代替。但是,当我使用 poll() 时,它不会执行处理程序。如果我尝试从 main() 显示 'receive_buffer' 的内容,我会得到全 0。有趣的是,当我单步执行访问 'receive_buffer' 元素的代码时,我确实得到了正确的值。
不确定我做错了什么。很有可能是小学生的错误。
当我将其转换为 MATLAB-Simulink 的 s 函数时,它会做同样的事情 - 全为零。
如有任何帮助,我们将不胜感激。
干杯,
在您的处理程序函数中,您需要在处理完答案后最后调用 socket.async_receive_from
。 io_service.run()
returns 当没有更多处理程序在其处理队列中时。
请在此处查看 boost 文档中的示例:udp sync server example
编辑
重新阅读您的 question/comment,我不确定您的预期输出或行为是什么。
如果您只需要一个 UDP 帧,那么可以调用 io_service.run_one()
。
如果您不想run()
阻塞您的主线程,您需要启动另一个线程来调用run()
。类似于:
boost::asio::io_service io_service;
// Process handlers in a background thread.
boost::thread t(boost::bind(&io_service::run, &io_service));
...
io_service::run()
始终是阻塞调用。只能从当前调用 run()
的线程调用完成处理程序。 run()
进入 return 的唯一时间是当队列中没有更多处理程序时(您停止调用 async_receive
)或者如果您通过调用显式取消 run()
命令stop()
或 reset()