我正在與其他使用sendto(..)和recvfrom()的UDP套接字運行相同程序的其他服務器(相同或相似系統)交換結構struct update_packet
。將struct結構化爲char *並通過UDP發送
基於從stackoverflow.com/questions/27055729/答案,我寫了一個函數來序列struct update_packet
struct update_packet {
uint16_t num_update_fields;
uint16_t port;
uint32_t IP;
vector<struct node> nodes;
const char * serialize() const {
ostringstream oss;
put_u16_as_big(oss, num_update_fields);
put_u16_as_big(oss, port);
put_u32_as_big(oss, IP);
for(size_t i = 0; i < num_update_fields; ++i) {
put_u32_as_big(oss, nodes[i].IP);
put_u16_as_big(oss, nodes[i].port);
put_u16_as_big(oss, nodes[i].nil);
put_u16_as_big(oss, nodes[i].server_id);
put_u16_as_big(oss, nodes[i].cost);
}
string str = oss.str();
cout << str << "\t" << str.size() << endl;
cout << str.data() << "\t" << sizeof(str.data()) << endl;
return str.data();
}
...
};
和put_u16_as_big
是一個輔助函數,它把一個uint16_t
大端爲參考ostringstream
。
void put_u16_as_big(ostringstream& oss, uint16_t data) {
if (is_big_endian()) {
oss.write((const char *)&data, sizeof(data));
}
else {
const char * ptr = (const char *)&data;
unsigned int s = sizeof(data);
for(unsigned int i=0; i < s; ++i) {
oss.put(ptr[s-1-i]);
}
}
}
然後它被實例化像
struct update_packet up;
const char * up_to_send = up.serialize();
和發送。
我把一些cout
在serialize()
進行測試。
隨着
cout << str << "\t" << str.size() << endl;
它打印怪異字符(數字在一個盒子),大小爲44
然而,str.data()
返回const char *
cout << str.data() << "\t" << sizeof(str.data()) << endl;
我得到
8
空字符串爲str.data()
和8大小
此外,當我接收通過UDP套接字的數據,並從recvfrom
打印的返回值,其是接收到的字節,它打印0,並且所接收的消息是相同種類的就像那個怪異的角色,但只有一個角色。
問題是什麼,如何解決這個問題,以便我可以在接收端接收和檢索數據?
項目規格要求大的字節順序。如何在Big Endian中寫入'ostringstream'並在接收端讀取它,如果它使用小端? – user2418202 2014-11-22 01:34:19
@ user2418202如果您將其轉換爲數字的字符串表示形式,那麼您將「排除」字節序。字節順序是數字在內存中的二進制表示所固有的。如果你想發送原始的二進制數據,那麼你應該發送它是「網絡字節順序」這是大端。這是一堆C庫函數,它將數字從主機字節順序轉換爲網絡字節順序,並返回:'htonl()','ntohl()'用於'long',還有一些用於'short' 。原始二進制和字符串表示都有優點和缺點... – rafeek 2014-11-25 16:11:41