如何逐个数据包地从C中的开放网络套接字接收数据(字节流)?我想在它到达时立即从套接字中读取数据(一旦数据包到达机器)。
当我在套接字上执行read()(或recv())调用时,我得到的是10,000+字节的整个TCP消息。相反,我希望收到第一个TCP段有效载荷,处理它,然后继续下一个,等等。
注意 - 我不想要原始数据包。只是TCP段数据有效载荷。
另请注意 - 实质上,我希望通过在数据到达时立即处理数据来最小化延迟,而不是等待整个TCP消息在TCP层中累积。
非常感谢任何想法,谢谢!
答案 0 :(得分:2)
也许我误解了你的问题(例如,我不能理解'不要只是TCP有效载荷的原始数据包'),而是连接一个简单的原始套接字(IPPROTO_TCP),然后用recv()嗅探会做的。您在recv()中指定最大缓冲区大小作为参数,但是当TCP负载到来时,它将被报告回来 - 无需等待缓冲区填满。以下是一些打印出TCP数据包的代码摘录:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include // your header to print out bytes and error messages here
int main(void) {
int i, recv_length, sockfd;
u_char buffer[9000];
if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
// your error message here
for(i=0; i < 3; i++) {
recv_length = recv(sockfd, buffer, 8000, 0);
printf("Got a %d byte packet\n", recv_length);
// your routine to print out bytes here
}
}
如果这不是你所关注的,请善意澄清。
编辑:从我听到和阅读的内容来看,使用库pcap(libcap)优于使用原始套接字(更可靠;功能非常强大 - 由编写tcpdump的人编写)。但是,我自己仍在学习pcap,到目前为止,我正在努力让它与无线设备一起正常工作。但是,如果你需要持续这样做,也许也要考虑一下。
答案 1 :(得分:1)
TCP没有“消息”。它只是一个字节流。套接字API不允许您访问单个IP数据包或TCP段所承载的数据。
但是,如果您想在操作系统提供一些数据时立即读取数据,那么
答案 2 :(得分:0)
您应该在数据到达后立即获取数据。没有“整个TCP消息”这样的东西。每次调用read
或recv
都应该为您提供当时收到的有序字节数。
答案 3 :(得分:0)
本质上,我希望通过在数据到达时立即处理数据来最小化延迟,
在内核套接字缓冲区中数据可用的时间与从阻塞read()
/ recv()
/ select()
中唤醒接收进程的时间之间存在调度延迟/ epoll()
/等。使用未经修改的Linux内核和实时进程,它不会少于4微秒。
如果您想避免调度延迟,一个选项是忙于轮询/等待,以防止操作系统将进程置于休眠状态。也就是说,在{0}超时调用select()
或在非阻塞套接字上调用recv()
并在返回EAGAIN
时立即重试该调用。显然,它必须是一个实时的FIFO进程,它不遵守调度程序时间片,否则会耗尽其时间片忙等待并将进入休眠状态。
而不是等待整个TCP消息在TCP层中累积。
要迂腐,就没有 TCP消息这样的东西。 TCP一旦到达就提供数据,只要它按顺序到达。