2010-06-19 237 views
1

我正在寫簡單的服務器/客戶端在c,其中服務器臨時存儲來自客戶端的消息,並在客戶端請求時檢索它。從插座讀取緩衝區

問題是當客戶端收到來自服務器的消息時,緩衝區有點奇怪。 所有我所做的是多讀,從服務器接收並打印在屏幕上,但不知何故,緩衝液overwrited比緩衝區的最大尺寸更

在客戶端

while((byteRead = recv(ssock, buffer, MAXBUF, 0)) > 0) 
{ 
    if(byteRead <= 0) 
     break; 
    printf("%s", buffer); 
} 

其中MAXBUF是256.保持包含一些garbages,所以我在緩衝 檢查字符串大小和令人驚訝的

printf("%d READ vs %d buffer strlen \n", byteRead, strlen(buffer)) 

告訴我,byteRead是256,但緩衝區的字符串長度爲262

任何想法?

P.s在服務器端,它正確讀取文件並將其發送到套接字上。

回答

13

recv不會在字符串的末尾放置空終止符(而printf%s假定有一個)。

您必須使用byteRead來確定字符串的長度。如果要使用printf之類的函數,請添加空終止符,但請確保即使在最大尺寸讀取時,緩衝區也有空間。

1

是的。

strlen()查找最近的NULL終止符,如在常規C字符串中一樣。

recv()與null結束符無關,不會添加一個。所以,strlen調用是錯誤的,甚至可能會因未經授權的讀取而導致程序崩潰。

+0

確定我得到了這一點。但在服務器端,當客戶端通過套接字向服務器發送消息時,它會正確接收並且我沒有添加空指針。即使我以爲我發送給客戶端之前我添加了空指針,它仍然顯示垃圾的東西; – REALFREE 2010-06-19 08:18:34

+0

@REALFREE:當我們說空終止符時,我們正在談論「nul」*字符*,而不是空*指針*。此外,在你的服務器的情況下,它可能會出現*工作,因爲祝你好運,但你做的事情不合適。 – Artelius 2010-06-19 08:50:11

4

這裏的問題是buffer不是由recv()以NULL結尾。實際上,recv只將原始套接字數據放入緩衝區。如果它接收到256字節的數據,那麼隨後出現的任何內容都可能爲空字符(例如它在服務器上),或者可能是其他內容(如它在客戶端上)。這是程序執行的一個神器,而不是你如何編程它。

的最簡單和最快的方式來解決這個問題:

  1. 分配buffer與大小MAXBUF + 1。 +1將用於額外的NULL字符。
  2. 緊接在printf之前,在buffer[bytesRead]處添加空字符。

所以全告訴:

buffer = malloc((MAXBUF + 1) * sizeof(char));   // NEW 

while((byteRead = recv(ssock, buffer, MAXBUF, 0)) > 0) 
{ 
    if(byteRead <= 0) 
     break; 
    else { 
     buffer[bytesRead] = '\0';      // NEW 
     printf("%s", buffer); 
    } 
}