getline over socket
是否有一个libc函数可以执行与getline相同的操作,但是可以使用连接的套接字而不是FILE *流吗?
解决方法是在套接字上调用fdopen。 在这样做的时候应该注意什么。 有什么理由去做/不去做。
这样做的一个明显原因是调用getline和co,但是重写一些自定义getline可能是个更好的主意吗?
当你在套接字上调用read时,它可以提前返回零值。 例如。
read(fd, buf, bufsize)
如果tcp套接字的内核缓冲区已满,则可以返回小于bufsize的值。 在这种情况下,可能需要再次调用读取函数,除非它返回零或负结果。
因此最好避免使用stdiofunction。 你需要为read函数创建包装器,以便实现迭代调用read以便可靠地获取bufsize字节。 只有当无法从套接字读取更多字节时,它才应返回零值,就像从本地磁盘读取文件一样。
你可以在Randal Bryant的“ 计算机系统:程序员的视角 ”一书中找到包装器。
源代码可在此站点获得。 寻找以rio_开头的函数。
问题是如果您没有收到新行(\ n或\ r \ n,取决于您的实现),程序将挂起。 我编写了你自己的版本,它也调用select()来检查套接字是否仍然是可读/写的并且没有任何错误。 真的没有办法判断是否会出现另一个“\ n”或“\ r \ n”,所以请确保您知道来自客户端/服务器的数据是否一致。
想象一下,您编写了一个使用getline()读取标题的Web服务器。 如果攻击者简单发送
GET / HTTP/1.1\r\n This line isn't terminated: bla
getline的调用永远不会返回,程序会挂起。 可能会花费您的资源,最终可能会出现DoS。
如果套接字连接到不可信输入,请准备在任意时间范围内进行任意输入
- \ r \ n之前的\ 0字符
- 永远等待\ r或\ n中的任何一个
- 任何其他可能丑陋的事情
解决任意时序和任意数据的一种方法是在读取上提供超时,例如通过select(2),并将实际接收的数据逐字节地提供给一些编写良好的状态机。