如何从套接字读取接收自定义数据类型?

时间:2015-10-25 09:41:59

标签: c++ sockets boost

我想收到一个数据(自定义类型说CMYType) 我有以下代码;

using namespace boost::asio;

streambuf receivedStreamBuffer;
streambuf::mutable_buffers_type bufs;
bufs = receivedStreamBuffer.prepare( sizeof(CMYType) );
std::size_t length = read( *m_pReciver->ConSocket(), 
                           buffer(bufs, sizeof(CMYType)),  
                           transfer_all(),
                           ec);

如何将receivedStreamBuffer转换为CMYType类型的对象?

2 个答案:

答案 0 :(得分:1)

您的代码"可以"实际工作。但是,正如Christophe指出的那样,您需要考虑许多问题。

TCP / IP编程

在您的评论中,您提到您是TCP / IP编程的新手。我建议你仔细阅读"Beej's guide to network programming"。这是一篇简短的(约20页)和体面的介绍,涵盖了网络编程的几乎所有方面,包括以下内容。这非常值得花时间,而且是免费的。

<强>字节序

这是网络通信的一般基本问题。如果您无法控制软件运行的机器,那么您绝对需要来处理它。或者如果你想要便携式代码。只有当您完全确定通信的两台(所有)机器具有相同的架构时,才可以跳过此

如果您需要了解更多问题,these three websites是很好的起点。

<强>序列化

序列化既是问题的概括,又是&#34;银弹&#34;这可以解决上述问题(如果正确应用)。基本思想是将您的数据类型(结构)转换为&#34;串行流&#34;可以通过任何渠道(网络)传输并转换回您的类型。 Boost有serialization library可用于此目的。

答案 1 :(得分:1)

请记住其他人提到的便携性和ABI警告。

如果您在评论中说,您确定您的客户端和服务器在这些方面兼容:

对于POD数据

如果您的类型符合POD要求,您可以使用buffer_cast

实际上你可以使用buffer函数隐含它:

<强> Live On Coliru

#include <boost/asio.hpp>
#include <iostream>
#include <vector>
#include <boost/thread.hpp>

struct CMYType {
    float a,b,c;
};

static_assert(std::is_pod<CMYType>::value, "Not bitwise serializable");

static std::ostream& operator<<(std::ostream& os, CMYType const& cmy) {
    return os << "[" << cmy.a << "," << cmy.b << "," << cmy.c << "]";
}

static boost::mutex mx;

void server() {
    boost::system::error_code ec;
    using namespace boost::asio;

    io_service svc;
    ip::tcp::acceptor acc(svc, ip::tcp::endpoint{ {}, 6767 });

    {
        ip::tcp::socket sock(svc);
        acc.accept(sock, ec);

        CMYType data;
        std::size_t length = read(sock, buffer(&data, sizeof(data)), ec);
        boost::lock_guard<boost::mutex> lk(mx);
        std::cout << "length:" << length << " data: " << data << "\n";
    }

    {
        ip::tcp::socket sock(svc);
        acc.accept(sock, ec);

        std::vector<CMYType> data(10);
        std::size_t length = read(sock, buffer(data), ec);

        boost::lock_guard<boost::mutex> lk(mx);
        std::cout << "length:" << length << " data: { ";

        for(auto& cmy : data)
            std::cout << cmy << ", ";

        std::cout << " }\n";
    }
}

void client() {
    boost::system::error_code ec;
    using namespace boost::asio;

    io_service svc;

    {
        ip::tcp::socket sock(svc);
        sock.connect({ {}, 6767 }, ec);

        CMYType data { 1, 2, 3 };

        std::size_t length = write(sock, buffer(&data, sizeof(data)), ec);
        boost::lock_guard<boost::mutex> lk(mx);
        std::cout << "sent: " << length << " bytes\n";
    }

    {
        ip::tcp::socket sock(svc);
        sock.connect({ {}, 6767 }, ec);

        std::vector<CMYType> data { 
            { 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 },
        };
        std::size_t length = write(sock, buffer(data), ec);

        boost::lock_guard<boost::mutex> lk(mx);
        std::cout << "sent: " << length << " bytes\n";
    }

}

int main() {
    boost::thread_group tg;
    tg.create_thread(server);
    tg.create_thread(client);

    tg.join_all();
}

打印

sent: 12 bytes
length:12 data: [1,2,3]
sent: 120 bytes
length:120 data: { [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],  }

对于非POD数据

您可以使用例如提升序列化以序列化数据