Recv()一次一行

时间:2011-12-01 00:23:02

标签: c sockets recv

我最近在学习如何在c中编写基本的网络服务器。我的服务器依赖于某些输入将发送各种文本行,所有文本都以空白行结束,我需要从客户端以某种方式接收它们,以便一次显示一行。

现在服务器执行类似

的操作
send(socket, sometext, strlen(sometext), 0)
send ...
send(socket, "\n", 2, 0);

....

客户端:

目前我正在做的是使用fdopen来包装套接字文件描述符并使用fgets读取:

FILE *response = fdopen(someSocket, "r");
while(1){
            fgets(input, 500, response);

        if(strcmp(input, "\n") != 0){
            //do some stuff
        }
        else {
            // break out of the loop
            break;
        }
}

这一切都很好,除了我的程序需要满足一个条件,那就是不要破坏套接字连接。因为我打开了一个文件,为了阻止内存泄漏,下一行是:

fclose(response);

然而,这是我的问题的根源,因为它不仅关闭文件,而且还关闭了我不能拥有的套接字。任何人都可以给我任何简单的方法来解决这个问题吗?我在考虑使用recv(),但是不是必须同时接收整个消息吗?有没有办法使用recv重新创建fgets的行为?

我真是个新手,感谢所有的帮助!

4 个答案:

答案 0 :(得分:2)

你遇到的另一个问题是,FILE可能已经从你的套接字中读取了更多的数据(通过空白行)并缓冲了它,如果你关闭FILE,它将会丢失。这两个问题的解决方案是不要关闭FILE - 只需在第一次创建套接字时创建一个FILE fdopen(紧跟connect或{{ 1}} call),并将其用于从套接字读取的所有数据。

另一个注意事项:accept会发送一个换行符和一个新行 - 您可能需要send(socket, "\n", 2, 0);send(socket, "\n", 1, 0);,具体取决于其他发送的内容。

答案 1 :(得分:1)

您应该尝试发送HTTP标头,然后将告诉您的客户有关内容的长度等等。这样您就不必检查任何换行符。

http://en.wikipedia.org/wiki/List_of_HTTP_header_fields

答案 2 :(得分:1)

你唯一真正的选择是编写一个函数:

1)使用固定缓冲区和循环调用recv(),

2)仅在您获得完整的行(或连接结束)时返回

3)保存任何“剩下的字符,以便下次阅读下一行文字

IIRC,史蒂文斯有这样的功能:

PS: 任何自尊的高级Web编程库都将为您提供基本免费的“getNextLine()”函数。

答案 3 :(得分:0)

POSIX有一个函数getline(3),你可能会在这里找到它。它位于stdio.h,原型是

ssize_t getline(char ** restrict linep, size_t * restrict linecapp, FILE * restrict stream);

它甚至可以调整缓冲区的大小(通过realloc(3)),使其足够大以容纳线条。

还有fgetln(3)类似,并且也有宽字符版本。然而,这不是标准。