簡體   English   中英

C ++如何通過套接字發送結構?

[英]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不直接包含數據。 他們指着它。 這意味着當您將包含向量的結構轉儲到套接字中時,您將轉儲指向內存的指針,但不會轉向指向的內容。 這將導致接收方(最多)崩潰。

這將排序為個人工作的personcar的對象。 它們不包含任何指針,因此它們的內存包含所有相關值

在發送方:

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-)

http://thrift.apache.org/

另外,它會發送二進制數據,因此您不必將數字轉換為字符串,反之亦然。 如果您的大部分數據都不是字符串,那么這樣做要快得多。

使用Boost序列化庫:

http://www.boost.org/doc/libs/1_48_0/libs/serialization/doc/index.html

對於此類任務而言,這可能是最強大,通用,可靠,易於使用甚至跨平台的方式。

正如其他人已經說過的那樣,使用某種序列化庫將提供最強大(也可能是最簡單的維護)解決方案。 但是,如果您真的想要自己實現它,那么以下顯示了如何處理它的“想法”。 以下分配緩沖區,然后使用employees矢量內容填充它。 變量c假定為company類型。

有些事情需要注意:

  • 該示例使用緩沖區為單個發送加載多個條目。 對於UDP,通常不希望一次發送一個條目,因為它將導致每個條目一個分組。
  • 存儲在緩沖區中的第一個值是項目數。 實際上,可能需要一些額外的信息(例如,數據類型)。 否則,接收者不一定知道它得到了什么。
  • char數據被復制並以null結束。 另一種方法是使用長度為數據加前綴並放棄空終止符。
  • 將整數值存儲在4字節邊界對齊的緩沖區中(取決於系統)可能是明智的。
  • 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM