如何使用 boost asio 通过 UDP 套接字发送无符号字符的 std::vector?



这是我之前问题的扩展,其中包含代码的">最小可行示例"。

我开发了一个UDPClient & UDPServer应用程序,如下所示。这些应用程序与boost官方udp客户端和boost官方udp服务器非常相似:

UDPClient.cpp

#include <iostream>
#include <algorithm>
#include <boost/asio.hpp>
using boost::asio::ip::udp;
struct Person {
char name[1024];
int age;
};
int main(int argc, char* argv[]) {
// Turn this variable TRUE on to send structs of "Person"
bool send_structs = false;
try {
if (argc != 2) {
std::cerr << "Usage: client <host>" << std::endl;
return 1;
}
boost::asio::io_service io_service;
udp::resolver resolver(io_service);
udp::resolver::query query(udp::v4(), argv[1], "7123");
udp::endpoint receiver_endpoint = *resolver.resolve(query);
udp::socket socket(io_service);
socket.open(udp::v4());
for (;;) {
if (send_structs == true) {
// Send structs
Person send_data = { "something_from_client", 123 };
boost::system::error_code ignored_error;
socket.send_to(boost::asio::buffer(&send_data, sizeof(send_data)), receiver_endpoint, 0, ignored_error);
udp::endpoint sender_endpoint;
Person receive_data;
std::size_t len = socket.receive_from(boost::asio::buffer(&receive_data, sizeof(receive_data)), sender_endpoint);
std::cout << "After receiving at client header is " << receive_data.name << std::endl;
std::cout << "After receiving at client version is " << receive_data.age << std::endl;
}
else {
// Send & receive char vectors
std::vector<unsigned char> send_data(1024);
std::string str = "Hello from Client";
std::copy (str.begin(),str.begin(), send_data.begin());
boost::system::error_code ignored_error;
std::cout << "Before sending vector length is " << send_data.size() << std::endl;
socket.send_to(boost::asio::buffer(send_data.data(), send_data.size()), receiver_endpoint, 0, ignored_error);
udp::endpoint sender_endpoint;
std::vector<unsigned char> receive_data;
receive_data.resize(1024);
std::size_t bytes_rec = socket.receive_from(boost::asio::buffer(receive_data), sender_endpoint);
std::cout << "After receiving at client vector size is " << receive_data.size() << std::endl;
std::cout << "Received bytes at client are " << bytes_rec << std::endl;
}
}
}
catch (std::exception& e) {
std::cerr << e.what() << std::endl;
}
return 0;
}

UDPServer.cpp

#include <iostream>
#include <algorithm>
#include <boost/asio.hpp>
using boost::asio::ip::udp;
struct Person {
char name[1024];
int age;
};
int main() {
// Turn this variable TRUE on to send structs of "Person"
bool send_structs = false;
try {
boost::asio::io_service io_service;
udp::socket socket(io_service, udp::endpoint(udp::v4(), 7123));
for (;;) {
udp::endpoint remote_endpoint;
if (send_structs == true) {
// Send structs
boost::system::error_code error;
Person receive_data;
size_t len = socket.receive_from(boost::asio::buffer(&receive_data, sizeof(receive_data)), remote_endpoint, 0, error);
std::cout << "After receiving at server header is " << receive_data.name << std::endl;
std::cout << "After receiving at server version is " << receive_data.age << std::endl;
if (error && error != boost::asio::error::message_size)
throw boost::system::system_error(error);
boost::system::error_code ignored_error;
Person send_data = { "something_from_server", 456 };
socket.send_to(boost::asio::buffer(&send_data, sizeof(send_data)), remote_endpoint, 0, ignored_error);
}
else {
// Send & receive char vectors
boost::system::error_code error;
std::vector<unsigned char> receive_data;
receive_data.resize(1024);
std::size_t bytes_rec = socket.receive_from(boost::asio::buffer(receive_data), remote_endpoint, 0, error);
std::cout << "Bytes received at server are " << bytes_rec << std::endl;
std::cout << "After receiving at server vector length is " << receive_data.size() << std::endl;
if (error && error != boost::asio::error::message_size)
throw boost::system::system_error(error);
boost::system::error_code ignored_error;
std::vector<unsigned char> send_data(1024);
std::string str = "Hello from Server";
std::copy (str.begin(),str.begin(), send_data.begin());
std::cout << "Before sending vector length is " << send_data.size() << std::endl;
std::size_t bytes_sent = socket.send_to(boost::asio::buffer(send_data.data(), send_data.size()), remote_endpoint, 0, ignored_error);
std::cout << "Bytes sent from server are " << bytes_sent << std::endl;
}
}
}
catch (std::exception& e) {
std::cerr << e.what() << std::endl;
}
return 0;
}

我正在使用以下编译命令在 clang OSX 上构建应用程序:

clang++ -std=c++14 -lboost_system UDPClient.cpp -o UDPClient
clang++ -std=c++14 -lboost_system UDPServer.cpp -o UDPServer

像这样在控制台上运行应用程序。在客户端启动之前先运行服务器:

./UDPServer
./UDPClient <host_ip>

问题是这样的:

当我通过将布尔标志send_structs设置为两侧的true来发送结构时,它可以很好地发送结构。但是当我在两边send_structs设置为 false 并尝试相同的技术发送std::vector<unsigned char>时,奇怪的是它不起作用。

那么,如何使用升压 asio 通过 UDP 套接字发送unsigned charstd::vector

服务器应用日志的快照:

After receiving at server vector length is 0
Before sending vector length is 1024
Bytes sent from server are 1024
Bytes received at server are 0
After receiving at server vector length is 0
Before sending vector length is 1024
Bytes sent from server are 1024
Bytes received at server are 0
After receiving at server vector length is 0

客户端应用日志的快照:

Before sending vector length is 1024
After receiving at client vector size is 0
Received bytes at client are 0
Before sending vector length is 1024
After receiving at client vector size is 0

如您所见,接收后矢量长度为零!

PS:我还注意到,在发送结构时,当我首先启动服务器时,它会等到客户端打开套接字。但是,在发送向量时,服务器只是盲目地保持发送循环。这是我的代码或预期行为中的错误吗?(次要问题)

如果要接收到向量中,则必须调整缓冲区的大小以指示要接收的数量。这正是这个答案中发生的事情:提升 asio 写/读向量

现在,这个:

std::vector<unsigned char> receive_data;
std::size_t bytes_rec = socket.receive_from(boost::asio::buffer(receive_data), sender_endpoint);

请求接收 0 字节(因为接收缓冲区的大小为 0)。

您可能知道预期的数据报大小。否则,您可以简单地过度调整缓冲区的大小,因为接收bytes_rec会告诉您已接收到多少元素。

最新更新