2016-11-29 69 views
0

我目前正在爲Linux編寫一個套接字包裝器。它基本上是處理TCP套接字的創建,連接,發送,讀取和關閉的類的集合。C++套接字只發送前4個字節的數據

在我的套接字類中,除了發送和接收函數外,所有函數都能正常工作。他們不會返回錯誤;相反,它只發送前四個字節的數據。

我的發送功能:

int Socket::sends(char* buffer){ 

    int bytes; // for number of bytes sent 

    /* First, send the size of buffer */ 
    int datalen = strlen(buffer); // get sizeof buffer 
    int len  = htonl(datalen); // reformat 

    // send the size of the buffer 
    bytes = send(socketfd, (char*)&len, sizeof(len), 0); // send the size 
    if (bytes < 0){ 
     cerr << "Error sending size of buffer to socket" << endl; 
     return 1; 
    } 

    /* Now acutally send the data */ 

    bytes = send(socketfd, buffer, datalen, 0); 
    if (bytes < 0){ 
     cerr << "Error writing buffer to socket" << endl; 
     return 1; 
    } 

    cout << bytes << " written" << endl; 

    return 0; 

} 

其背後的想法是,這將首先發送緩衝區的大小,然後發送實際的緩衝區的緩衝區(char* buffer)。如果遇到一個錯誤(返回-1)函數通過返回1

現在終止,這裏是讀法:

int Socket::reads(char* buffer){ 

    int bytes, buflen; // for bytes written and size of buffer 

    /* Read the incoming size */ 
    bytes = recv(socketfd, (char*)&buflen, sizeof(buflen), 0); 
    if (bytes < 0){ 
     cerr << "Error reading size of data" << endl; 
     return 1; 
    } 
    buflen = ntohl(buflen); 

    /* Read the data */ 

    bytes = recv(socketfd, buffer, buflen, 0); 
    if (bytes < 0){ 
     cerr << "Error reading data" << endl; 
     return 1; 
    } 

    return 0; 
} 

在這裏,想法是先讀取數據的大小,然後將緩衝區設置爲該大小並讀入。錯誤時函數返回1(recv返回-1)。

使用方法會是這個樣子:

socket.sends("Hello World"); // socket object sends the message 

char* buffer; 
socket.reads(buffer); // reads into the buffer 

然而,當過我使用這些功能,我只收到了前4個字節的數據,其次是陌生的,非ASCII字符。我不知道爲什麼會發生這種情況。 sendrecv函數中沒有遇到錯誤,函數說明只寫入4個字節。有更好的方法來發送或接收數據嗎?我忽略了一個非常簡單的錯誤?

感謝您的幫助!

+1

請注意,C和C++是不同的語言。請僅使用相關標籤。 – kaylum

+2

你怎麼知道有足夠的內存分配給讀取?示例代碼創建一個名爲「buffer」的指針,但不會將其指向任何分配的內存。 –

+1

如果您使用的是非阻塞套接字,'recv'可能會讀取任意數量的字節(包括0),您需要調用'recv'直到獲得所有數據或返回錯誤。 – alain

回答

4

您正在將未初始化的指針(buffer)傳遞給您的reads方法,這可能說明它部分工作(未定義的行爲)。

,你不應該通過buffer作爲參數,因爲它不會被修改(和你不知道的大小尚未反正)

另外,你必須用空字符結束,當你收到您的留言它。

我會做這樣的:

char *Socket::reads(){ 
    char* buffer; 
    int bytes, buflen; // for bytes written and size of buffer 

    /* Read the incoming size */ 
    bytes = recv(socketfd, (char*)&buflen, sizeof(buflen), 0); 
    if (bytes < 0){ 
     cerr << "Error reading size of data" << endl; 
     return 1; 
    } 
    buflen = ntohl(buflen); 
    buffer = new char[buflen+1]; // +1 for the NUL-terminator 
    /* Read the data */ 

    bytes = recv(socketfd, buffer, buflen, 0); 
    if (bytes < 0){ 
     cerr << "Error reading data" << endl; 
     return 1; 
    } 
    buffer[buflen] = '\0'; // NUL-terminate the string 

    return buffer; 
} 

主:

socket.sends("Hello World"); // socket object sends the message 

char* buffer = socket.reads(); // reads into the buffer 

不要忘記delete []到底緩衝區。

也可以用std::stringstd::vector<char>做是爲了避免newdelete

+0

這是個好建議,但是如果OP的'buffer'足夠大,就沒有UB。它不是未初始化的,它大概是分配的,然後傳遞給函數。 – alain

+0

你可能是對的。也許我很快回答確定。我肯定是空終止部分。即使緩衝區足夠大,如果您沒有終止,您也會得到垃圾,因爲它沒有被髮送。 –

+0

當在OP末尾的代碼中出現'socket.reads(buffer);'時,''buffer'顯然是未初始化的。 –