2017-05-07 146 views
2

我有一個大學的項目,我必須實施迭代服務器如何清理使用read()填充的緩衝區並繼續讀取相同的緩衝區?

服務器使用教授給出的協議,用幾句話說,客戶端必須以特定的形式發送消息,我的服務器必須進行一些解析以便將某些數據保存在全局結構中。

我使用函數read()來接收消息並將其存儲在固定大小的char數組中。我的問題是,有時候這個消息可能比我用來存儲它的緩衝區的大小要大。 注意:我無法首先發送消息的大小以繞過此問題。

我想知道是否有辦法做到這一點。

貝婁是一些代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <string.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include "keyvalue.h" 
#include <errno.h> 

int main (int argc, char *argv[]) 
{ 
    char keyvaluebuffer[4096]; 
    int num; 
    //socket() 
    //bind() 
    //listen() 

    while(1) 
     { 
      //accept() 
      while((num = read(acceptfd, keyvaluebuffer, 4096)) > 0) 
       { 
        //At this point I use the keyvaluebuffer to parse it and store the data. 
       }//while (read > 0) end 
      if (num < 0){close(accept);} 

      close(accept); 
     }//while(1) end  
    close(socket); 
}//main end 
+1

是否有某些原因不會動態分配'keyvaluebuffer',根據需要重新分配? –

+0

@DavidBowling在一般情況下,我寧願與靜態數組解決方案,因爲它是我完全理解,但我想知道他們是否是一種方法來解決這個問題,使用malloc()。 – arkas

+0

問題是什麼?爲什麼你不能使用更大的緩衝區?注意這裏沒有'靜態數組'。這是一個局部變量。 – EJP

回答

0

如果消息比緩衝區大小,那麼你將至少需要已檢索的消息的一部分存儲讀取更多的前信息。一種選擇是動態分配消息緩衝區。在將部分消息讀入靜態緩衝區之後,它將被複制到動態消息緩衝區中。如果動態消息緩衝區已填充,則重新分配。

在下面的示例代碼中,buffer[]是一個數組,其中包含BUF_SIZEchar s。 msg是一個指向動態分配內存的指針,最初指向BUF_SIZE字節。 msgbuff_sz跟蹤動態消息分配的大小,而msg_sz跟蹤實際消息大小。在每次調用read()後,buffer[]的內容被複制到msg中的適當位置,msg_sz被更新。如果消息大小與消息緩衝區大小相同,則重新分配消息緩衝區msg。這一直持續到達到文件結束條件(或直到read()返回錯誤值)。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <fcntl.h> 
#include <unistd.h> 

#define BUF_SIZE 4096 

int main(void) 
{ 
    int fd = open("message.txt", O_RDONLY); 
    if (fd < 0) { 
     perror("Unable to open file"); 
     exit(EXIT_FAILURE); 
    } 

    char buffer[BUF_SIZE]; 
    char *msg = malloc(BUF_SIZE); 
    size_t msgbuff_sz = BUF_SIZE; 
    size_t msg_sz = 0; 

    if (msg == NULL) { 
     perror("Buffer allocation error"); 
     exit(EXIT_FAILURE); 
    } 

    ssize_t ret_val; 

    while ((ret_val = read(fd, buffer, sizeof buffer)) > 0) { 
     memcpy(msg + msg_sz, buffer, ret_val); 
     msg_sz += ret_val; 
     if (msg_sz == msgbuff_sz) { 
      msgbuff_sz += BUF_SIZE; 

      char *tmp = realloc(msg, msgbuff_sz); 

      if (tmp == NULL) { 
       perror("Buffer reallocation error"); 
       exit(EXIT_FAILURE); 
      } 
      msg = tmp; 
     } 
    } 

    if (ret_val < 0) { 
     perror("Unable to read file"); 
     exit(EXIT_FAILURE); 
    } 

    for (size_t i = 0; i < msg_sz; i++) { 
     putchar(msg[i]); 
    } 
    putchar('\n'); 

    free(msg); 

    return 0; 
} 
+0

非常感謝您對最新回答感到抱歉。你的方式似乎運作良好,但有一個小問題。 while(read()> 0)永遠不會退出。 ret_val永遠不會變爲零。 – arkas

+0

我的答案更關心緩衝存儲問題,並且在從文件讀取時工作。如果另一端關閉套接字,read()應該返回0。如果不是,處理這種情況可能會稍微複雜一些。有一些討論的問題[這裏](http://stackoverflow.com/questions/3053757/read-from-socket)和[這裏](http://stackoverflow.com/questions/666601/what-is-所述-正確路-的讀取-從-A-TCP-插座中-CC)。 –