如何在逐个数据包的基础上从C中的开放网络套接字接收数据(字节流)?我想在它到达时立即从套接字读取数据(一旦数据包到达机器) .
当我在套接字上执行read()(或recv())调用时,我得到的是10,000字节的整个TCP消息 . 相反,我希望收到第一个TCP段有效载荷,处理它,然后继续到下一个,等等 .
注意 - 我不想要原始数据包 . 只是TCP段数据有效载荷 .
还要注意 - 实质上我希望通过在数据到达时立即处理数据来最小化延迟,而不是等待整个TCP消息在TCP层中累积 .
任何想法将不胜感激,谢谢!
4 回答
TCP没有“消息” . 它只是一个字节流 . 套接字API不允许您访问单个IP数据包或TCP段所承载的数据 .
但是,如果您想在操作系统为您提供一些数据时立即读取数据,那么您就可以了
使用套接字描述符上的fcntl()调用将套接字设置为非阻塞模式 .
使用I / O通知服务注册套接字描述符,例如select(),poll(),epoll .
等待此服务上的I / O事件 .
当指示套接字已准备好读取时,您可以从中读取 - 然后您将获得当时可用的大量数据 . (并处理read / recv返回-1且errno设置为EWOULDBLOCK的情况)
您应该在数据到达时立即获取数据 . 没有"entire TCP message"这样的东西 . 每次调用
read
或recv
都应该为您提供当时收到的有序字节数 .也许我误解了你的问题(例如,我不能完全理解'不希望原始数据包只是TCP有效负载'),但连接一个简单的原始套接字(IPPROTO_TCP),然后使用recv()嗅探将执行工作 . 您在recv()中指定最大缓冲区大小作为参数,但是当TCP负载到来时,它将被报告回来 - 无需等待缓冲区填满 . 以下是一些打印出TCP数据包的代码摘录:
如果这不是您所关注的,请善意澄清 .
编辑:从我听到和阅读,使用库pcap(libcap)优于使用原始套接字(更可靠;非常强大 - 由编写tcpdump的人写的) . 但是,我自己仍在学习pcap,到目前为止,我正在努力让它与无线设备一起正常工作 . 但是,如果您需要持续进行此操作,也许可以考虑一下 .
在内核套接字缓冲区中数据可用的时间与从阻塞中唤醒接收进程的时间之间存在调度延迟
read()
/recv()
/ 1217772 /epoll()
/等 . 使用未经修改的Linux内核和实时进程,它不会少于4微秒 .如果您想避免调度延迟,一个选项是忙于轮询/等待,以防止操作系统将进程置于休眠状态 . 也就是说,在非阻塞套接字上调用带有0超时的
select()
或调用recv()
,如果它返回EAGAIN
,则立即重试该调用 . 显然,它必须是一个不遵守调度程序时间片的实时FIFO进程,否则它会耗尽其时间片忙等待并将进入休眠状态 .为了迂腐,没有TCP消息这样的东西 . TCP一旦到达就提供数据,只要它按顺序到达 .