2015-10-26 68 views
1

我想通過使用send()和recv()在http上傳輸一個結構(有數據和ID等)。通過TCP,以下兩行完美地工作。使用套接字發送一個結構通過http

Client: send(sock, (char *)&StructToSend, sizeof(StructToSend), 0); 
Server: recv(sock, (char *)&StructToRecv, sizeof(StructToRecv),0); 

但是,當通過HTTP,在StructToRecv只得到兩個字節凌亂這樣的代碼:EE

////Client code: send over http 
    int length = 0; 
    char header[4096]; 
    char tmp_name[80]; 
    memset(tmp_name, 0, sizeof(tmp_name)); 
    strcat_s(tmp_name, "tmp.txt"); 

    length = (sizeof(SendStruct)+strlen(tmp_name)+ 287); 

    sprintf_s(header, "POST /%s/index.html HTTP/1.1\r\n", sub_dir; 
    sprintf_s(header, "%sHost: %s \r\n", header , szIP); 
    sprintf_s(header, "%sUser-Agent: Mozilla/5.0 (Windows NT 6.1; rv:32.0) Gecko/20100101 Firefox/32.0\r\n", header); 
    sprintf_s(header, "%sAccept: text/html;q=0.9,*/*;q=0.8\r\n", header); 
    sprintf_s(header, "%sAccept-Language: en-US,en;q=0.5\r\n", header); 
    sprintf_s(header, "%sAccept-Encoding: gzip, deflate\r\n", header); 
    sprintf_s(header, "%sConnection: Keep-Alive\r\n", header); 
    sprintf_s(header, "%sContent-Type: multipart/form-data; boundary=-----------------------------26774670897926\r\n", header); 
    sprintf_s(header, "%sContent-Length: %d\r\n", header, length); 
    sprintf_s(header, "%s\r\n", header); //blank line 
    sprintf_s(header, "%s-------------------------------26774670897926\r\n", header); 
    sprintf_s(header, "%sContent-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n", header, tmp_name); 
    sprintf_s(header, "%sContent-Type: text/plain\r\n", header); 
    sprintf_s(header, "%s\r\n", header); //blank line 
    sprintf_s(header, "%s%s\r\n", header, (char *)&StructToSend); 
    sprintf_s(header, "%s-------------------------------26774670897926\r\n", header); 
    sprintf_s(header, "%sContent-Disposition: form-data; name=\"submit\"\r\n", header); 
    sprintf_s(header, "%s\r\n", header); 
    sprintf_s(header, "%sSubmit\r\n\r\n", header); 
    sprintf_s(header, "%s-------------------------------26774670897926--\r\n\r\n\0", header);  

    send(sock, header, sizeof(header), 0); 


    ////Server code : recv over http 
    char http_data[4096] = { '\0' }; 
    ZeroMemory(http_data, sizeof(http_data)); 
    recv(sock, http_data, 4096, 0); 
+0

你的'sprintf_s()'調用之一缺少一個右括號;代碼顯示無法編譯。 'sprintf_s()'的C11附件K定義是:'int sprintf_s(char * restrict s,rsize_t n,const char * restrict format,...);'即使微軟可能不完全匹配('int sprintf_s(char * buffer,size_t sizeOfBuffer,const char * format [,argument] ...);',作爲第二個參數沒有傳入一個大小會導致可怕的作弊行爲,也無法可靠地傳遞目標字符串('header ')作爲要處理的參數之一 - 它會產生未定義的行爲**重新考慮!** –

+1

請注意,不推薦使用這種方式發送結構(通過HTTP,TCP或任何其他協議),因爲內存結構的佈局不能保證在網絡連接的兩側都是相同的,如果它不同,接收方會誤解傳入的數據。發送數據的正確方式是文本或成員數據項通過成員數據項,這樣就可以很好地定義線上數據格式(許多程序員選擇使用serializ ation library來處理這個任務) –

+0

@JeremyFriesner我不應該使用第三個庫。我該如何解決這個問題? –

回答

3
sprintf_s(header, "%s%s\r\n", header, (char *)&StructToSend); 

您正在使用sprintf(...%s..)。這意味着您給出的數據被視爲以\0結尾的字符串,即只包含直到第一個\0的數據。

+0

我應該使用什麼?有代碼的任何建議嗎? –

+0

我應該首先將StructToSend轉換爲char字符串嗎? –

+0

@MinKim:你不能使用像sprintf,strcpy,strlen等任何字符串函數和包含'\ 0'的二進制數據。字符串函數僅適用於(非二進制)字符串,其他所有內容都使用memcpy和類似的函數。 –