2013-11-15 34 views
1

我有一個學校的任務,一部分是發送一套整數,字符char *從客戶端到服務器使用套接字編程。發送整數或字符工作得很好,但有什麼辦法可以將整個結構作爲一個包發送嗎?閱讀關於序列化,但我似乎無法使其工作。這裏有一個代碼片段:發送數據從一個結構,套接字編程

The struct looks like this: 
struct Msg 
{ 
     int a; 
     char b; 
     char *user; 
}; 

Client: 
init variables and such... 
int netcom(char* ip, int port) { 
    sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 
    // clear the structure 
    bzero(&serveraddr, sizeof(struct sockaddr_in)); 
    serveraddr.sin_family = AF_INET; 
    // add the server adress 
    inet_pton(AF_INET, ip, &serveraddr.sin_addr); 
    // add the port number 
    serveraddr.sin_port = htons(port); 
    // connect 
    connect (sd,(struct sockaddr*)&serveraddr, sizeof(struct sockaddr_in)); 
} 

int sendPkg(struct Msg msg) { 
    send(sd, &msg, sizeof(msg), 0); 
} 

和接收這樣長相的服務器的一部分:

char buf[100]; 
recv(sd[i], buf, sizeof(buf)-1, 0); 

客戶發送完美的罰款,並接收服務器的罰款。但我不知道我要發送什麼,以及如何正確閱讀。所以這是我的問題。如何使用套接字正確發送來自struct的數據。

+1

您需要閱讀http://en.wikipedia.org/wiki/Serialization。無法發送指針。即char * –

+1

另外,TCP是一個STREAM服務,而recv()返回一個你需要使用的值。 –

回答

5

直接發送一個結構看起來很吸引人,因爲你可以在一次調用中完成它......而且更糟糕的是:有時候它實際上會工作得很好!儘管這是一個陷阱。

這是一個陷阱的第一個原因是,例如,在你的情況下,其中一個元素是一個指針。除非常罕見的情況,接收者將得到那個在這方面無用的指針 - 指針指向對發送進程有效的內存。

第二個也是不太明顯的原因是這個陷阱是一個套接字一側的結構佈局(在內存中)在另一側可能不完全相同。這是機器體系結構和編譯器設置的一個功能,因此相信它會「一切正常」並不安全。這個陷阱很容易脫離一段時間,特別是在開發過程中,您可能在測試的每一側都有兼容的體系結構。

最好的辦法是單獨發送每個字段,即使這很痛苦。通過爲代碼創建一個專用的發送者和接收者函數,您可以通過在代碼中應用一些面向對象的設計來減少它的痛苦。這些功能對內容和訂單有深入的瞭解,並將其打包成更小的發送(如果您的文件爲char *,可能需要在字符串數據之前包含一個長度)。

只要結構沒有從套接字的一端改變到另一端,我描述的打包發送就沒有問題,但是您可能希望在一端具有不同版本的結構時保持警惕。 ..說一個新的(或不存在的)領域。爲了解決這個問題,你可以考慮標記你發送的數據(而不是假設「首先我們發送a,然後b等)」。

查看許多JSON庫來管理序列化將是有益的。這爲您提供了一種易於閱讀的格式,可解決我在此處介紹的所有問題,並且幾乎可爲所有常見編程語言提供JSON庫。