[英]C++ How to send structures over socket?
說我有一個結構:
struct person
{
char name[10];
int age;
};
struct car
{
int locationX;
int locationY;
};
struct company
{
vector<person> employees;
vector<car> cars;
};
例如,我想使用套接字(UDP) send/recv
整個company
。 所以,發送和recv一次。
我怎樣才能做到這一點? 你能給我一些代碼嗎? 如何發送所有內容並閱讀所有內容。
謝謝!
您的問題的措辭表明您正在尋找的是:
company foo;
send(sockfd, &foo, sizeof(foo), 0); // DO NOT do this
這基本上會將company
結構的所有內存轉儲到您的套接字中。 這將不會在這種情況下工作 。 即使它有點工作,這也是一個非常糟糕的主意。 它不起作用的原因是vector
s不直接包含數據。 他們指着它。 這意味着當您將包含向量的結構轉儲到套接字中時,您將轉儲指向內存的指針,但不會轉向指向的內容。 這將導致接收方(最多)崩潰。
這將排序為個人工作的person
或car
的對象。 它們不包含任何指針,因此它們的內存包含所有相關值
在發送方:
person joe = { "Joe", 35 };
send(sockfd, &joe, sizeof(joe), 0); // may work, but is a bad idea, see below
在接收方:
person joe;
recv(sockfd, &joe, sizeof(joe), 0);
但是,這仍然是一個壞主意。 它依賴於發送方和接收方,它們的結構具有完全相同的存儲器布局。 出於各種原因,這可能不是真的。 有些包括一個在PowerPC芯片上,另一個在Intel x86芯片上。 或者一個在使用Visual Studio編譯的Windows機器上,另一個在使用gcc編譯的Linux機器上。 或許有人調整了一些編譯器標志,導致默認結構布局不同。 有很多原因。
真的,你應該像所有人建議的那樣使用序列化框架。 我會建議谷歌協議緩沖區或其他人已經鏈接到的Boost序列化框架 。 但還有很多其他的。
另一個序列化框架應該被提及,因為它非常快(幾乎與直接將結構的內存映像轉儲到套接字中一樣快)是Cap'n Proto 。
請查看Google協議緩沖區http://code.google.com/apis/protocolbuffers/,作為Boost序列化的精簡替代方案。
如果你要做很多這些,你可能想要看看Thrift。 它將自動生成所有必要的代碼,以便為您序列化所有結構,因此您無需手動執行此操作。
他們支持字符串也非常實用。
哦! 它是免費的。 8-)
另外,它會發送二進制數據,因此您不必將數字轉換為字符串,反之亦然。 如果您的大部分數據都不是字符串,那么這樣做要快得多。
使用Boost序列化庫:
http://www.boost.org/doc/libs/1_48_0/libs/serialization/doc/index.html
對於此類任務而言,這可能是最強大,通用,可靠,易於使用甚至跨平台的方式。
正如其他人已經說過的那樣,使用某種序列化庫將提供最強大(也可能是最簡單的維護)解決方案。 但是,如果您真的想要自己實現它,那么以下顯示了如何處理它的“想法”。 以下分配緩沖區,然后使用employees矢量內容填充它。 變量c
假定為company
類型。
有些事情需要注意:
htonl
用於以網絡字節順序存儲整數值。 接收端應使用ntohl
讀取它們。 簡單而非常不完整的例子:
// allocate buffer to store all the data for a send. In a real world
// this would need to be broken up into appropriately sized chunks
// to avoid difficulties with UDP packet fragmentation.
// This likely over-allocates because the structure likely has padding
char *buf = new char[ sizeof( uint32_t ) + // for total number of entries
sizeof( person ) * c.employees.size() ]; // for each entry
char *pos = buf;
// Indicate how many are being sent
*(uint32_t*)pos = htonl( c.employees.size() );
pos += sizeof uint32_t;
for ( vector<person>::iterator pi = c.employees.begin();
pi != c.employees.end(); pi++ )
{
*(uint32_t*)pos = htonl( pi->age );
pos += sizeof uint32_t;
strcpy( pos, pi->name );
pos += strlen( pi->name ) + 1;
}
send( 0, buf, (int)( pos - buf ), 0 );
delete [] buf;
// The receiving end would then read the number of items and
// reconstruct the structure.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.