2011-08-25 68 views
4

我正在構建一個UDP聊天應用程序。它安全地通過c套接字發送C結構,並在另一端memset接收數據? struct中的所有數據都與memset無效,所以我假設結構的大小始終爲常量。我可能遇到什麼問題?通過c socket發送結構

更有經驗的程序員如何接近這個?

+0

考慮尋找協議緩衝區http://code.google.com/p/protobuf/ – Jack

回答

6

是的,它是安全的,但我們應該警告這個第一。你可能遇到問題如果你在不同的平臺之間傳遞它,然後你需要擔心字節排序/打包(之間的其他一些問題可能)。話雖如此,如果你不知道如何做到這一點,那麼假設你可以按照你發送的順序可靠地收到struct是不安全的。

+3

這可能是一個非常嚴重的問題! –

+0

我相信PPC和MIPS是兩個不同字節順序的平臺。您通常可以在遊戲系統和網絡設備(如WiFi路由器)中找到這些芯片。 –

+0

不同的包裝很容易找到:32位和64位系統通常會以不同方式包裝整數。 –

1

你必須要小心,你的結構不包含指針(如char*字符串)。當您在結構中存儲std::string時也適用,因爲std::string中有一個指針。

5

但是你這樣做,單元測試地獄出來。編譯器和平臺在這些方面差異很大,所以千萬不要盲目認爲它是一致的。

編譯器可以在它們的隨心所欲改變結構對準(出於性能原因,例如)。詢問一些限制一般都是具體的編譯器,雖然這是一個由MSVC和gcc(通過擴展),支持

#pragma pack(push, 1) 
struct Foo { 
    // .. 
}; 
#pragma pack(pop) 

這迫使它在1個字節邊界對齊,所以沒有布爾值。

如果你想成爲完全兼容,然後自己序列化的每個字段。這真的不是所有的工作。

您還必須處理字節排列順序,如其他人所說。

+0

在新的C++ 11標準,這個'#pragma pack'擴展將不再需要,因爲我們有'alignas'說明符:) –

+0

這真是個好消息。我一直在支持下發現很多這類東西。 –

+0

是的,但你必須等待一段時間。儘管編譯器已經實現了很多大的C++ 11特性,但是我沒有知道的編譯器實現了'alignas'但是:( –

3

struct中的所有數據都是memset與memset,所以我假設結構的大小始終是常量。

這並沒有什麼意義。對象總是有一個固定的大小。 「使用memset無紙化」與它無關。

它安全地發送C結構在C套接字和另一端memset接收到的數據?

不,不是真的。

更好地考慮發送「數據」而不是內存中對象的確切字節方式的物理內容。

我可能遇到什麼問題?

  • 會員填充
  • 數據對齊
  • 類型大小
  • 字節序
  • 的間接—指針數據,而不是數據本身

如何更有經驗的程序員approachi這個?

最好做好序列化。

創建一個數據格式,您的應用程序無論在哪臺機器上都能識別,並用它來表示您的聊天數據。

  1. 有時爲了提高效率,你必須設計一個二進制格式,並使用聰明,健壯的技術來正確deserialise在目標計算機上的信息,以上面列出的因素考慮在內。

  2. 但是,對於簡單的工作,您可以使用人類可讀的文本格式。不能真的出問題了。

+1

@Downvoter:習慣性地解釋你自己。 –

+0

+1我認爲這是一個很好的答案,因爲它清楚地解釋了所有問題。 OTOH,如果你小心並且有一個計劃來處理你可能遇到的每個問題,我會認爲C被設計爲允許這樣的事情如果你知道如何正確地做到這一點。 –

+0

@Ken:我不認爲C是,但是遵循其任務的一些實現可能是。 –