我正在使用网络信使来通过TCP / IP发送和接收Message
个对象。通常,消息包含基元std::string
;或者字符串向量但是,有些情况下我需要发送UTF16 Unicode std::wstring
。
据我所知,从TCP的角度来看,无论如何,所有内容都将被转换为字节数组(char
),因此应该可以按字节顺序发送这些wstring
。在接收和反序列化之后,我强制将数据转换为其在标题中声明的相应messageType。
消息如下所示:
class ConcreteMessage: public Message
{
private:
std::wstring m_myString;
int aPrimiteVariable;
public:
// serializes the messages variables and sends it to the MemoryStream
void save(util::MemoryStream& out)
{
out << aPrimiteVariable;
size_t len = m_myString.size(); // length of the string (number of wchar_t's)
out << len;
size_t sz = m_myString.size() * sizeof(wchar_t); // effective size of the string (len * 2 bytes on Windows)
out << sz;
/// send the wstring to the MemoryStream
if (sz)
out.write((const unsigned char*)m_myString.c_str(), sz);
}
/// does the same thing in reverse to deserialize the message. Must be done in the exact same order!
void load(util::MemoryStream& in)
{
in > aPrimiteVariable;
size_t len;
in >> len;
m_myString.resize(len);
size_t sz;
in >> sz;
if (sz)
in.read((unsigned char*)&m_myString.front(), sz);
}
};
我使用扩展basic_stringstream
进行解/序列化:
#pragma once
#include <sstream>
namespace util {
class MemoryStream : public std::basic_stringstream<unsigned char>
{
typedef std::basic_stringstream<unsigned char> TBase;
public:
MemoryStream()
{
}
MemoryStream(const unsigned char* begin_, const unsigned char* end_)
: TBase(std::basic_string<unsigned char>(begin_, end_))
{
}
template<typename T>
MemoryStream& operator <<(T i) {
return writePrimitive(i);
}
template<typename T>
MemoryStream& operator >>(T& i) {
return readPrimitive(i);
}
template<typename T>
MemoryStream& operator <<(std::basic_string<T> s) {
size_t len = s.length();
writePrimitive(len);
write(reinterpret_cast<const unsigned char*>(s.c_str()), len * sizeof(T));
}
template<typename T>
MemoryStream& operator >>(std::basic_string<T>& s) {
size_t len = 0;
readPrimitive(len);
util::ScopedArray<T> buf(new T[len + 1]);
memset(buf.get(), 0, (len + 1) * sizeof(T));
read(reinterpret_cast<unsigned char*>(buf.get()), len * sizeof(T));
s = buf.get();
}
private:
template<typename T>
MemoryStream& writePrimitive(T t)
{
write(reinterpret_cast<const unsigned char*>(&t), sizeof(t));
return *this;
}
template<typename T>
MemoryStream& readPrimitive(T& t)
{
read(reinterpret_cast<unsigned char*>(&t), sizeof(t));
return *this;
}
};
template<typename T>
inline
MemoryStream& operator <<(MemoryStream& st, T t)
{
return st.operator <<(t);
}
template<typename T>
inline
MemoryStream& operator >>(MemoryStream& st, T& t)
{
return st.operator >>(t);
}
}
请注意,此类继承std::basic_stringstream<unsigned char>
而非wchar_t
现在,在接收此类数据时,我需要将其转换为相应的消息类:
if (ConcreteMessage* msg = dynamic_cast<ConcreteMessage*>(m))
// etc....
首先:到目前为止一切顺利(令人惊讶)。但是,有大量的reinterpret_cast
和dynamic_cast
s,它感觉有点脏。
你认为这种方法有什么严重的问题吗?
我总是听说你永远不应该使用reinterpret_cast
和&#39; dynamic_cast&#39;,但是在分布式系统上进行这样的序列化处理时,有没有办法避免它们? / p>