![](/img/trans.png)
[英]How to simply serialize complex structures and send them over a network in Qt
[英]How to serialize an object to send over network
我正在嘗試序列化對象,通過僅使用STL的套接字通過網絡發送。 我沒有找到一種方法來保持對象的結構在其他主機中反序列化。 我嘗試轉換為string
,轉換為char*
,我花了很長時間在互聯網上搜索教程,直到現在我什么都沒發現。
有沒有辦法只用STL做到這一點?
有沒有好的教程?
我差點嘗試提升,但如果有STL怎么做我想學習。
你可以用任何東西序列化。 所有序列化的意思是您將對象轉換為字節,以便您可以通過流(如std::ostream
)發送它,並用另一個(如std::istream
)讀取它。 只需覆蓋operator <<(std::ostream&, const T&)
和operator >>(std::istream&, T&)
,其中T
是你的每個類型。 以及您的類型中包含的所有類型。
但是,你應該只使用一個已經存在的庫(Boost非常好)。 像Boost這樣的庫為你做了很多事情,比如字節排序,處理常見對象(比如數組和標准庫中的所有東西),提供了執行序列化和大量其他東西的一致方法。
我的第一個問題是:你想要序列化還是消息傳遞?
一開始看起來似乎很愚蠢,因為你要求序列化,但是我總是區分這兩個術語。
我經常看到人們使用Serialization,其中應該使用Messaging。 這並不意味着序列化是無用的,但它確實意味着你應該提前思考。 一旦您決定對其進行序列化,就很難改變BOM,特別是如果您決定重新定位某些信息(將其從一個對象移動到另一個對象)...因為您將如何解碼“舊”序列化版本?
現在已經清理了......
......我會推薦谷歌的協議緩沖區。
你可以使用STL完全重寫你自己,但你最終會完成已經完成的工作,除非你想從中學習,否則它是毫無意義的。
關於protobuf
一個protobuf
是它在某種程度上與語言無關:即你可以為C ++,Java或Python生成給定消息的編碼器/解碼器。 使用Python非常適合消息注入(測試)或消息解碼(檢查記錄消息的輸出)。 如果您使用STL,這不是一件容易的事情。
這已經晚了6年,但我最近遇到了這個問題,這是我在搜索如何通過C ++中的網絡套接字序列化對象時遇到的線程之一。 該解決方案僅使用2或3行代碼。 我發現有很多答案,但我發現最簡單的方法是使用reinterpret_cast<obj*>(target)
將類或結構轉換為字符數組並通過套接字提供它。 這是一個例子。
要序列化的類:
/* myclass.h */
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass
{
public:
int A;
int B;
MyClass(){A=1;B=2;}
~MyClass(){}
};
#endif
服務器程序:
/* server.cpp */
#include "myclass.h"
int main (int argc, char** argv)
{
// Open socket connection.
// ...
// Loop continuously until terminated.
while(1)
{
// Read serialized data from socket.
char buf[sizeof(MyClass)];
read(newsockfd,buf, sizeof(MyClass));
MyClass *msg = reinterpret_cast<MyClass*>(buf);
std::cout << "A = " << std::to_string(msg->A) << std::endl;
std::cout << "B = " << std::to_string(msg->B) << std::endl;
}
// Close socket connection.
// ...
return 0;
}
客戶計划:
/* client.cpp */
#include "myClass.h"
int main(int argc, char *argv[])
{
// Open socket connection.
// ...
while(1)
{
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
MyClass msg;
msg.A = 1;
msg.B = 2;
// Write serialized data to socket.
char* tmp = reinterpret_cast<char*>(&msg);
write(sockfd,tmp, sizeof(MyClass));
}
// Close socket connection.
// ...
return 0;
}
使用g++
編譯server.cpp和client.cpp,並選擇-std=c++11
。 然后,您可以打開兩個終端並運行這兩個程序,但是,在客戶端之前啟動服務器程序,以便它可以連接到某些程序。
希望這可以幫助。
我認為你應該在你的項目中使用谷歌協議緩沖區。在網絡傳輸協議緩沖區有許多優於XML的序列化結構化數據的優勢。 協議緩沖區:
更簡單的是3到10倍小,快20到100倍,更少模糊生成數據訪問類,更容易使用programmaticall
等等。 我想你需要閱讀關於protobuf的https://developers.google.com/protocol-buffers/docs/overview
我知道了!
我使用strinstream來序列化對象,並使用stringstream的方法str()和字符串的c_str()將其作為消息發送。
看。
class Object {
public:
int a;
string b;
void methodSample1 ();
void methosSample2 ();
friend ostream& operator<< (ostream& out, Object& object) {
out << object.a << " " << object.b; //The space (" ") is necessari for separete elements
return out;
}
friend istream& operator>> (istream& in, Object& object) {
in >> object.a;
in >> object.b;
return in;
}
};
/* Server side */
int main () {
Object o;
stringstream ss;
o.a = 1;
o.b = 2;
ss << o; //serialize
write (socket, ss.str().c_str(), 20); //send - the buffer size must be adjusted, it's a sample
}
/* Client side */
int main () {
Object o2;
stringstream ss2;
char buffer[20];
string temp;
read (socket, buffer, 20); //receive
temp.assign(buffer);
ss << temp;
ss >> o2; //unserialize
}
我不確定是否有必要在序列化之前轉換為字符串(ss << o),也許可以直接從char。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.