在 MSG_DONTWAIT 模式下使用 recvfrom() 从原始套接字读取以太网数据包
reading Ethernet data packet from raw sockets using recvfrom() in MSG_DONTWAIT mode
我使用原始套接字在 C 语言中使用 recvFrom() 发送和接收以太网数据包。我想以非阻塞模式阅读,所以我使用 MSG_DONTWAIT。但是 recvFrom() 总是返回 -1,无论是否接收到数据包。我是 C 编程的新手。
我能够收到我的负载,但我总是收到消息 "Receive resource temporary unavailable"。
代码片段:
if ((sock = socket(AF_PACKET, SOCK_RAW, htons(0x8851))) < 0) {
perror("ERROR: Socket");
exit(1);
}
while(1) {
int flag=0;
n=recvfrom(sock, buffer, 2048, MSG_DONTWAIT, NULL, NULL);
if (n == -1) {
perror("ERROR: Recvfrom");
close(sock);
flag=1;
}
if (flag==0) {
// Read Packet
}
}
如果你对recvfrom()使用MSG_DONTWAIT参数,系统调用总是会立即return无论是否有任何数据要读取。如果没有数据,则 return 值为 -1,然后 errno 将设置为 EAGAIN。在您的申请中,我不完全确定 MSG_DONTWAIT 是正确的选择。如果您唯一要做的就是从那个套接字读取数据包,那么您不应该使用 MSG_DONTWAIT。因此,您的程序实际上会循环打印大量错误消息。如果在 errno == EAGAIN 的情况下删除该错误消息,您的程序会稍微好一些但不会好很多:它会在一个循环中旋转,消耗所有 CPU 资源。
但是,如果您同时读取多个文件描述符,那么使用非阻塞 I/O 是正确的选择。但是你应该有一个循环,而不是你的循环,使用 select()、poll() 或 epoll_wait() 轮询多个文件描述符的准备情况。由于您在 Linux 上 运行,我强烈推荐 epoll_wait(),因为它是这些方法中最具扩展性的方法。有关详细信息,请参阅 Linux 上的 epoll、epoll_wait 和 epoll_create 手册页。
我强烈建议暂时不要使用 MSG_DONTWAIT 并检查函数是否调用过 return。如果它从不 returns,这意味着它没有收到任何数据包。
我使用原始套接字在 C 语言中使用 recvFrom() 发送和接收以太网数据包。我想以非阻塞模式阅读,所以我使用 MSG_DONTWAIT。但是 recvFrom() 总是返回 -1,无论是否接收到数据包。我是 C 编程的新手。 我能够收到我的负载,但我总是收到消息 "Receive resource temporary unavailable"。
代码片段:
if ((sock = socket(AF_PACKET, SOCK_RAW, htons(0x8851))) < 0) {
perror("ERROR: Socket");
exit(1);
}
while(1) {
int flag=0;
n=recvfrom(sock, buffer, 2048, MSG_DONTWAIT, NULL, NULL);
if (n == -1) {
perror("ERROR: Recvfrom");
close(sock);
flag=1;
}
if (flag==0) {
// Read Packet
}
}
如果你对recvfrom()使用MSG_DONTWAIT参数,系统调用总是会立即return无论是否有任何数据要读取。如果没有数据,则 return 值为 -1,然后 errno 将设置为 EAGAIN。在您的申请中,我不完全确定 MSG_DONTWAIT 是正确的选择。如果您唯一要做的就是从那个套接字读取数据包,那么您不应该使用 MSG_DONTWAIT。因此,您的程序实际上会循环打印大量错误消息。如果在 errno == EAGAIN 的情况下删除该错误消息,您的程序会稍微好一些但不会好很多:它会在一个循环中旋转,消耗所有 CPU 资源。
但是,如果您同时读取多个文件描述符,那么使用非阻塞 I/O 是正确的选择。但是你应该有一个循环,而不是你的循环,使用 select()、poll() 或 epoll_wait() 轮询多个文件描述符的准备情况。由于您在 Linux 上 运行,我强烈推荐 epoll_wait(),因为它是这些方法中最具扩展性的方法。有关详细信息,请参阅 Linux 上的 epoll、epoll_wait 和 epoll_create 手册页。
我强烈建议暂时不要使用 MSG_DONTWAIT 并检查函数是否调用过 return。如果它从不 returns,这意味着它没有收到任何数据包。