在 C 中立即(逐包)从套接字接收 TCP 有效负载

发布于 2024-12-05 04:30:50 字数 301 浏览 2 评论 0原文

如何从 C 中的开放网络套接字逐包接收数据(字节流)?我想在数据到达时立即从套接字读取数据(数据包到达机器后)。

看来当我在套接字上执行 read() (或 recv())调用时,我收到了 10,000+ 字节的整个 TCP 消息。相反,我想接收第一个 TCP 段有效负载,处理它,然后继续下一个,等等。

注意 - 我不需要原始数据包。只是 TCP 段数据有效负载。

另请注意 - 本质上,我希望通过在数据到达时立即处理数据来最大程度地减少延迟,而不是等待整个 TCP 消息在 TCP 层中累积。

任何想法将不胜感激,谢谢!

How can I receive data (byte stream) from an open network socket in C on a packet-by-packet basis? I want to read data from the socket IMMEDIATELY as it arrives (as soon as the packet arrives on the machine).

It seems when I perform a read() (or recv()) call on the socket, I am getting the entire TCP message of 10,000+ bytes. Rather, I would like to receive the first TCP segment payload, process it, then continue to the next, etc.

Note - I don't want raw packets. Just the TCP segment data payload.

Also note - In essence I want to minimize delay by processing data immediately as it arrives, as opposed to waiting for the entire TCP message to accumulate in the TCP layer.

Any ideas would be much appreciated, thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

糖粟与秋泊 2024-12-12 04:30:50

也许我误解了你的问题(例如,我不太明白“不想要原始数据包,只需要 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,到目前为止正在努力让它与无线设备正常工作。但如果您持续需要这个,也许也可以研究一下。

Maybe I misunderstand your question (eg, I can't quite make sense of 'don't want raw packets just the TCP payload'), but a simple raw socket (IPPROTO_TCP) connected and then sniffed on with recv() will do the job. You indicate a maximum buffer size as an argument in recv(), but when a TCP load comes, it will be reported back - no waiting for the buffer to fill up. Here is some code excerpt that prints out TCP packets:

#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
    }
}

If this isn't what you were concerned about, kindly clarify.

Edit: From what I hear and read, using library pcap (libcap) is superior to using raw sockets (more reliable; very powerful - written by the guys who wrote tcpdump). However, I'm still learning pcap myself and so far am struggling to get it to work properly with wireless devices. But maybe look into that too if you need this on an on-going basis.

最美不过初阳 2024-12-12 04:30:50

TCP 没有“消息”。它只是一个字节流。套接字 API 不允许您访问单个 IP 数据包或 TCP 段所携带的数据。

但是,如果您希望在操作系统为您提供一些数据后立即读取数据,则可以

  1. 使用套接字描述符上的 fcntl() 调用将套接字设置为非阻塞模式。
  2. 向 I/O 通知服务注册套接字描述符,例如 select()、poll()、epoll。
  3. 等待此服务上的 I/O 事件。
  4. 当表明套接字已准备好读取时,您可以从中读取 - 并且您将获得当时可用的数据量。(并处理 read/recv 返回 -1 且 errno 设置为 EWOULDBLOCK 的情况)

TCP does not have "messages". It is just a byte stream. The socket APIs does not give you access to the data carried by individual IP packets, or TCP segments.

However, if you want to read data as soon as the operating system can give you some data, you

  1. Set the socket to non-blocking mode, using the fcntl() call on the socket descriptor.
  2. Register the socket descriptor with an I/O notification service , such as select(), poll(), epoll.
  3. Wait for I/O events on this service.
  4. When it's indicated a socket is ready for reading, you read from it - and you will get however much data is available at that time.(and handle the case where read/recv returns -1 and errno is set to EWOULDBLOCK)
月亮坠入山谷 2024-12-12 04:30:50

您应该在数据到达后立即获取数据。不存在“完整的 TCP 消息”这样的东西。每次调用 readrecv 都应该为您提供当时收到的尽可能多的有序字节。

You should be getting the data as soon as it arrives. There is no such thing as an "entire TCP message". Each call to read or recv should give you as many in-order bytes as have been received at that time.

无所谓啦 2024-12-12 04:30:50

本质上,我希望通过在数据到达时立即处理数据来最大程度地减少延迟,

在内核套接字缓冲区中数据可用的时间与接收进程从阻塞读取中唤醒的时间之间存在调度延迟( )/recv()/select()/epoll()/等等。在未修改的 Linux 内核和实时进程的情况下,它不少于 4 微秒。

如果您想避免调度延迟,一种选择是繁忙轮询/等待,以防止操作系统将进程置于睡眠状态。也就是说,以 0 超时调用 select() 或在非阻塞套接字上调用 recv() 并在返回 EAGAIN 时立即重试调用>。显然,它必须是一个不遵守调度程序时间片的实时FIFO进程,否则它将因忙于等待而耗尽其时间片并进入睡眠状态。

而不是等待整个 TCP 消息在 TCP 层中累积。

迂腐地说,不存在 TCP 消息这样的东西。 TCP 在数据到达后立即传送数据,前提是数据按顺序到达。

In essence I want to minimize delay by processing data immediately as it arrives,

There is a scheduling delay between the time when data becomes available in the kernel socket buffer and the time when the receiving process is woken up from a blocking read()/recv()/select()/epoll()/etc. With unmodified Linux kernel and a real-time process it is no less than 4 microseconds.

If you'd like to avoid the scheduling delay one option is to busy poll/wait preventing the OS from putting the process to sleep. That is, calling select() with 0 timeout or calling recv() on a non-blocking socket and retrying the call immediately if it returns EAGAIN. Obviously, it must be a real-time FIFO process which doesn't obey scheduler time slices, otherwise it will exhaust its time slice busy waiting and will be put to sleep.

as opposed to waiting for the entire TCP message to accumulate in the TCP layer.

To be pedantic, there is no such thing as TCP message. TCP delivers the data as soon as it arrives, provided it has arrived in order.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文