2011-11-26 120 views
1

我需要getline()来读取我的浏览器发送到我正在编程的Web服务器的请求标头。这是GetMessage函数这是应该做的任务:C getline函数不读取指定行

char *getMessage(int fd) { 
    FILE *sstream = fdopen(fd, "r"); 
    // initialise block to 1 char and set it to null 
    char *block = malloc(sizeof(char)); 
    *block = '\0'; 
    int size = 1; 

    // Read from the file descriptor fd (using a FILE stream) until a blank line is 
    // received. 
    // Read 100 lines (buffersize) from sstream and put into the buffer. If lines have 
    // been successfully read concatenate them with block. 
    int buffersize = 100; 
    char *buffer = malloc (buffersize + 1); 

    while(getline(&buffer,&buffersize,sstream) != -1){ 
    int length = strlen(buffer); 
    printf("Buffer length: %d\n",length); 
    block = realloc(block,strlen(block)+strlen(buffer)+1); 
    strcat(block,buffer); 
    if(strcmp(buffer,"\r\n") == 0) break; 
} 

    int len = strlen(block); 
    printf("Block length: %d\n", len); 
    printf("%s \n", block); 
    return block; 
} 

基本上GetMessage函数(FD)的输入,是在我的主要方法宣告我的听力套接字的输入。我已经验证输出是正确的。现在我需要将文件描述符的输出转换为一个字符串并返回该字符串。但是,每次运行我的服务器时,它都会停留在while循环中。不执行循环中的语句。 编辑:添加了循环终止条件:现在它跳转到“块长度”immediatley。 非常感谢帮助!

回答

5

如果您使用的是POSIX 2008 getline()函数,那么您将丢失有用的信息(它会返回它读取的行的长度,因此如果捕获该信息,则循环中不需要strlen()

如果getline()调用中的代码块可能意味着上游套接字未关闭,但没有数据被再次发送。您的发送代码需要关闭套接字,以便此代码可以检测到EOF。或者,由于您讨论'空白行',因此也许您的代码应该检查一行仅包含的行210(或者只是\n)并打破循环;你的代码目前没有这样做。

由于您反复使用strcat(),因此您的循环也显示二次方行为。你最好在tab字符串的末尾加上制表符,然后简单地在旧的数据后面输入新的数据,然后将指针调整到字符串的末尾。


在进一步审查,我注意到您使用fdopen()打开基于文件描述文件流,但是你既没有关闭它,也没有文件流返回给调用者进行封闭。这导致泄漏问题。

经验法则:如果你分配资源,你应该释放它,或者把它传回来释放。

我建议改变界面使用已经打开FILE *,做调用代码的fdopen()。或者,如果您不再需要文件描述符,则可以保留当前接口并在返回之前使用fclose(),但这也会关闭底层文件描述符。

此代码对我的作品(MacOS X的10.7.2; 4.2.1的XCode):

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

extern char *getMessage(FILE *); 

char *getMessage(FILE *fp) 
{ 
    char *block = 0; 
    size_t size = 0; 
    size_t buffersize = 0; 
    char *buffer = 0; 
    ssize_t newlen; 

    while ((newlen = getline(&buffer, &buffersize, fp)) > 0) 
    { 
     printf("Buffer length: %ld\n", (long)newlen); 
     block = realloc(block, size + newlen + 1); 
     strcat(&block[size], buffer); 
     size += newlen; 
     if (strcmp(buffer, "\r\n") == 0) 
      break; 
    } 

    printf("Block length: %zd\n", size); 
    if (size > 0) 
     printf("<<%s>>\n", block); 
    return block; 
} 

int main(void) 
{ 
    char *msg; 
    while ((msg = getMessage(stdin)) != 0) 
    { 
     printf("Double check: <<%s>>\n", msg); 
     free(msg); 
    } 
    return 0; 
} 

我用DOS样式行结尾作为标准输入文件进行了测试,既有一个空行作为最后一行和非空白行。连续两条空白行似乎也没问题。

+0

喜加STRCMP语句跳出循环。仍然没有改变!是的,正如你所说的那样,一旦我收到传输的结尾,规范就会停止阅读。但即使增加休息也没有改变。没有循环中断,因此我得到“块长度:0”。 – Abhischek

+0

@codaddict指出的问题也是有效的 - 你的编译器应该毫不含糊地告诉你这个问题。如果不是,则没有打开足够的警告。 –

+0

呃!我注意到'realloc()'代码有'space = realloc(space,new_size)'内存泄漏反模式,并且没有错误检查。重复'strcat()'是次优的(导致二次行为)。我应该找到写这个的人并让他们修复它......哦......好吧,我应该修复它。它适用于没有错误的玩具样品。 –

5
char buffer = (char *) malloc (buffersize + 1); 

应该是:

char *buffer = malloc (buffersize + 1); 
+0

好,但我认为你仍然想明确地将void *赋予char * –

+1

@RobertMartin:http://stackoverflow.com/questions/953112/should-i-explicitly-cast-mallocs-return-value – codaddict