我已經閱讀了BG的網絡編程入門,但一個主題仍然有問題:數據封裝。
基本上我創建了一個包含數據長度和消息的結構。例如:數據封裝(網絡編程)
struct Data
{
int length;
std::string message;
}
如何發送?使用send()
函數,我只能發送char *類型的變量。
另外,當我發送它時,在服務器端,我應該創建一個由封裝指定的長度的動態緩衝區並將消息打包到它?
我已經閱讀了BG的網絡編程入門,但一個主題仍然有問題:數據封裝。
基本上我創建了一個包含數據長度和消息的結構。例如:數據封裝(網絡編程)
struct Data
{
int length;
std::string message;
}
如何發送?使用send()
函數,我只能發送char *類型的變量。
另外,當我發送它時,在服務器端,我應該創建一個由封裝指定的長度的動態緩衝區並將消息打包到它?
C++中的常用方法是提供可以將自定義類型序列化爲'流'對象的函數,然後提供一種獲取指向流中累積的數據塊開始的指針的方法。
的一個簡單的例子是的std :: ostringstream,您可以使用數據序列化爲流,然後獲得一個指向構造的字符串:
int i = 13;
std::string message = "Hi";
std::ostringstream stream;
stream << i << message;
cout << stream.str() << endl; // prints "13Hi";
你可以爲你的Data
類型做同樣的通過在提供<<
和>>
運營商的適當的過載,如:
std::ostringstream &operator<<(std::ostringstream &stream, const Data &v) {
return stream << v.length << v.message;
}
std::ostringstream &operator>>(std::ostringstream &stream, Data &v) {
return stream >> v.length; >> v.message;
}
使用這些功能,你可以這樣做:
Data myData = { 13, "Hello" };
std::ostringstream stream;
stream << myData;
const std::string serializedData = stream.str();
send(.., serializedData.c_str(), serializedData.size() + 1, ..);
在接收大小,你可以將數據讀入緩衝區,然後使用std::istringstream
對象再次提取數據:
const char receivedData[ 1024 ];
// fill receivedData array using recv()
std::string s = receivedData;
std::istringstream stream(s);
Data myData;
stream >> myData;
您可能需要緩衝所接收的數據位,直到從閱讀該流成功。
Send()使用char *來允許以一個字節的倍數發送任何二進制數據。你有沒有嘗試鑄造到char *?
在接收端,你必須解開前幾個字節才能發現長度。當然,這種方法假定發送者和接收者使用相同長度的整數。您還應該小心發送給編譯器的打包參數。
您絆倒的主題是「序列化」,而不是封裝。 – tenfour 2011-03-28 16:19:28
+1對如何做到這一點的C++方式很好奇。你也應該問你是否需要擔心endian問題。 – Jeff 2011-03-28 20:57:33