如何使用boost asio通过UDP套接字发送无符号字符的std :: vector? [英] How to send an std::vector of unsigned char over an UDP socket using boost asio?

查看:108
本文介绍了如何使用boost asio通过UDP套接字发送无符号字符的std :: vector?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我以前的问题的扩展最小可行示例".

This is a extension to my previous question here with a "minimum viable example" of the code.

我已经开发了UDPClient& UDPServer应用程序如下.这些应用与 boost官方非常相似. udp客户端& 增强官方udp服务器:

I have developed a UDPClient & UDPServer app as below. These apps are very much similar to the boost official udp client & boost official udp server:

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;
}

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

I am building the apps on clang OSX with following compile command:

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

像这样在控制台上

运行应用.在客户端启动之前首先运行服务器:

Run the apps on console like so. Run the server firstly before client has started:

./UDPServer
./UDPClient <host_ip>

这是问题所在:

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

When I send structs by setting boolean flag send_structs as true on both sides then it works all fine sending the structs nicely. But when I set send_structs as false on both sides & try the same technique to send an std::vector<unsigned char>, it strangely doesn't work.

那么,如何使用boost asio在UDP套接字上发送unsigned charstd::vector?

So, How can I send an std::vector of unsigned char over an UDP socket using boost asio?

服务器应用日志快照:

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:我还注意到,在发送结构时,当我首先启动服务器时,它会一直等到客户端打开套接字. 但是,当发送向量时,服务器只是盲目地保持发送循环.这是我的代码中的错误还是预期的行为? (第二个问题)

PS: I also noticed that while sending the structs, when I start the server firstly, it waits until the client has opened the socket. But, when sending vectors, server just blindly keeps looping on the send. Is that a mistake in my code or expected behaviour? (secondary question)

推荐答案

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

If you want to receive into a vector, you will have to size the buffer to indicate how much you want to receive. This is exactly what happened in this answer: boost asio write/read vector

现在,这个:

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

要求接收0个字节(因为接收缓冲区的大小为0).

Asks to receive 0 bytes (because the size of the receiving buffer is 0).

您可能知道预期的数据报大小.否则,您可以简单地将缓冲区的尺寸过大,因为接收到的bytes_rec会告诉您已经接收了多少个元素.

You might know the expected datagram size. Otherwise, you can simply over-dimension the buffer, because the received bytes_rec will tell you how many elements have been received.

这篇关于如何使用boost asio通过UDP套接字发送无符号字符的std :: vector?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆