我目前有一個基本的客戶端/服務器設置。服務器需要從客戶端獲取請求並需要響應不同的請求消息類型。客戶端請求的一個例子可能是獲取可用文件列表,還有多少其他客戶端連接到服務器等。這在C/C++套接字通信中是否合理?
我顯然必須找出一種方法來確定從接收到的消息中的消息類型發件人。我想知道,如果我有一個用必要數據定義的結構,那麼我是否可以將結構強制轉換爲void *,通過發送(sockfd,message,length,flags)系統調用,並在接收端進行發送回到結構。這當然假定我在同一個環境中運行客戶端和服務器。
舉例來說,如果我有以下結構:
struct message {
enum messageType { GET_FILES, GET_CLINET_NUMBER} messageType,
}
,並使用該結構以如下方式
struct message msg;
msg.messageType = GET_FILES;
send(server_sockfd, (void*)&msg, sizeof(struct), 0)
,並在接收器上發送消息,
recv(,msg_buffer);
struct message received = (struct message*)msg_buffer;
忽略這些小的語法問題,任何人都可以建議這個方案是否可行?如果沒有,是否有任何其他方式來傳遞消息而不發送原始char *?
另一個,甚至可能更糟的問題:填充字節。 C++編譯器有時會在結構的成員之間添加'不可見'填充字節,以便爲目標CPU提高內存訪問效率。填充不是標準化的,所以它可以在一個編譯器和另一個編譯器之間,或者在同一個編譯器的兩個版本之間,甚至在來自同一個編譯器版本的構建之間(特別是如果它們使用不同的優化級別構建時)不同地完成。因此,除非連接的兩端都運行完全相同的可執行二進制文件,否則事情可能會中斷。 – 2011-06-05 18:35:48
對齊在給定的ISA ABI上是標準化的,並且在任何實字機器上,填充是對齊所需的最小值。而且,對於真實世界機器上的幾乎所有類型,對齊都是類型的大小。對齊必須總是*均勻地分割*類型的大小(由於C數組表示語義),所以如果設計的結構是這樣的,那麼在沒有填充的情況下,每個元素將以其大小的倍數開始,那麼你可以基本確定沒有填充。 – 2011-06-05 18:52:55