2013-08-29 95 views
3

我有一個問題給你。C++如何通過套接字發送對象?

我有這個類:

`

#define DIMBLOCK 128 
#ifndef _BLOCCO_ 
#define _BLOCCO_ 

class blocco 
{ 
    public: 
     int ID; 
     char* data; 


     blocco(int id); 
}; 

#endif 




blocco::blocco(int id) 
{ 
    ID = id; 
    data = new char[DIMBLOCK]; 
} 

`

和應用有一個客戶端和服務器。 在我的服務器的主體中,我用這種方式實例化了這個類的一個對象: blocco a(1);

之後,我使用套接字打開客戶端和服務器之間的連接。 現在的問題是:如何將這個對象從服務器發送到客戶端或反之亦然? 你能幫我嗎?

+0

可能需要套接字代碼。即使如此,除非你建立了一個精心製作的RPC系統,否則你得到的最好的結果就是*副本*(這可能是你所需要的)。 – WhozCraig

回答

5

在字面意義上,不可能通過TCP連接發送對象。套接字只知道如何傳輸和接收字節流。所以你可以做的是通過TCP連接發送一系列字節,格式化的方式是接收程序知道如何解釋它們並創建一個與發送程序想要發送的對象相同的對象。

該過程被稱爲序列化(和接收端的反序列化)。序列化不是內置於C++語言本身,所以你需要一些代碼來完成它。它可以通過手工或使用XML,或通過Google協議緩衝區完成,也可以通過將對象轉換爲人類可讀文本併發送文本或任何其他方式來完成。

查看更多信息here

+0

所以,不可能這樣做:ret = send(sock,reinterpret_cast (&a),sizeof(blocco),0);? – rosekarma

+1

不可以。不會有多種原因,例如,它不會遵循指針(例如,以這種方式發送的blocco的接收器將接收(數據)指針的值而不是(數據)指向的字符,這不會有用)。它也不能正確處理填充和尾部問題。 –

+0

@rosekarma那會有什麼好處呢?你將如何編寫代碼來接收數據,因爲你幾乎不知道你發送了什麼字節。要編寫代碼來接收數據,首先需要知道的是ID有多少個字節進行編碼。但是你甚至不知道 - 更糟糕的是,如果你改變編譯器,平臺等等,它會改變。 –

2

你可以使用serialization來做到這一點。這意味着將對象拉成碎片,以便您可以將這些元素髮送到套接字上。然後你需要在連接的另一端重建你的班級。在Qt中有QDataStream class提供這樣的功能。結合QByteArray,您可以創建一個可以發送的數據包。想法很簡單:

發件人:

QByteArray buffer; 
QDataStream out(&buffer); 
out << someData << someMoreData; 

接收機:

QByteArray buffer; 
QDataStream in(&buffer); 
in >> someData >> someMoreData; 

現在你可能要提供額外的構造函數:

class blocco 
{ 
    public: 
     blocco(QDataStream& in){ 
      // construct from QDataStream 
     } 

     //or 
     blocco(int id, char* data){ 
      //from data 
     } 
     int ID; 
     char* data; 


     blocco(int id); 
}; 

extended example

-1

我不知道我會爲此付出多少傷害,但是我嘗試了這一點,儘管我應該分享它。我是套接字編程的初學者,所以不要生氣。

我所做的是我創建了一個類的大小的數組(代表服務器端的內存塊)。然後,我在客戶端編輯了內存塊,並將該塊內存作爲對象進行了類型轉換!我設法從客戶端發送一個對象到服務器。

示例代碼:

blocco *data; 
char blockOfData[sizeof(*data)]; 

if(recv(serverSocket, blockOfData, sizeof(*data), 0) == -1) { 
    cerr << "Error while receiving!!" << endl; 
    return 1; 
} 

data = (blocco *)blockOfData; 

現在你可以做任何你想用這個作爲一個指向對象這個數據。請記住,不要嘗試刪除/釋放此指針,因爲此內存已分配給堆棧上的數組blockOfData。

希望這有助於如果你想實現這樣的事情。 PS:如果你認爲我所做的是不好的編碼方式,請讓我知道爲什麼。我不知道爲什麼這是一個壞主意(如果這樣做實際上是個壞主意)。謝謝!!

+0

如果您想知道爲什麼這種方法無效,請嘗試在recv()返回後打印出'received'blocco對象的'data'成員項所指向的字符串。你會發現字符串沒有被傳輸,你會打印出垃圾或者(更可能)你的程序在試圖解引用數據的指針時崩潰,它被設置爲指向一個有效的地址發送者的內存空間,但不在接收者的內存空間中。 –

+0

我在我的macbook上實現了這一點,並在同一臺機器上同時運行客戶端和服務器。我成功地訪問了數據,並沒有面臨任何崩潰/垃圾值問題。也許如果我嘗試在具有不同endian系統的多個系統上執行此操作,我會遇到問題嗎? –

+0

我現在明白你的觀點,如果我有指點,我會面對這些問題。雖然如果我有一個字符串(我在我的代碼中),那麼我不會面對這些問題。 –