我最近在学习如何在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的行为?
我真是个新手,感谢所有的帮助!
答案 0 :(得分:2)
你遇到的另一个问题是,FILE
可能已经从你的套接字中读取了更多的数据(通过空白行)并缓冲了它,如果你关闭FILE
,它将会丢失。这两个问题的解决方案是不要关闭FILE
- 只需在第一次创建套接字时创建一个FILE
fdopen
(紧跟connect
或{{ 1}} call),并将其用于从套接字读取的所有数据。
另一个注意事项:accept
会发送一个换行符和一个新行 - 您可能需要send(socket, "\n", 2, 0);
或send(socket, "\n", 1, 0);
,具体取决于其他发送的内容。
答案 1 :(得分:1)
您应该尝试发送HTTP标头,然后将告诉您的客户有关内容的长度等等。这样您就不必检查任何换行符。
答案 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)
类似,并且也有宽字符版本。然而,这不是标准。