混淆了poll()和recvfrom()

我试图在C中实现一个发送/接收原始以太网帧的协议,并且在Linux环境中使用poll()recvfrom()遇到了一些问题。 我认为我的问题主要是概念性的,所以我现在要避免发布我的代码。

我有两个传入数据的套接字,并且poll()正被用于通过其返回值和关联的pollfd结构的状态来指示何时在任一套接字上准备好数据。 当我第一次运行这个程序的时候,这就是我的工作。 为了testing的目的,我只对ARP帧感兴趣,我可以使用poll()等待一个ARP帧到达。 当它到达时,我调用recvfrom()将数据复制到可以处理它的位置。 所有这一切工作正常。

问题是继续调用poll()继续报告数据已经准备好从套接字读取,即使没有新的数据到达套接字。 一旦我调用recvfrom()并从套接字中读取数据,我希望poll()等到新的帧到达之后才报告数据已准备好。 我之前从来没有使用poll() ,所以我不确定是否需要明确的步骤来“清除”描述符,以便它将停止导致poll()报告正在准备好的数据,直到有新帧出现为止。在调用poll()之前,我正在清除pollfd结构的revents成员,但每次调用poll()都将revents的值设置为1。

我已经浏览了poll()手册页,而且我还没有find有关此信息的运气。 我觉得我误解了socket / polling是如何在高层工作,所以任何帮助,将不胜感激。

这是我的大部分代码。 我实际上已经简化了这个例子的代码,只包含一个套接字。 所有这些也都被封装在课堂上,并且散播出去,但是像这样重写就再现了我的问题。 我的最终代码对API调用进行了错误检查,并复制我的接收缓冲区来处理框架,而不仅仅是打印内容,但除此之外它几乎是一样的。

 #include <stdio.h> #include <stdint.h> #include <sys/socket.h> #include <netinet/in.h> #include <fcntl.h> #include <poll.h> #include <linux/if_ether.h> int main() { uint8_t sendBuffer_[1536]; uint8_t receiveBuffer_[1536]; struct pollfd pollStruct[1]; printf("Making socket..."); int mySocket = socket( AF_PACKET, SOCK_RAW, htons(ETH_P_ARP) ); fcntl(mySocket, F_SETFL, O_NONBLOCK); char *options; options = "eth0"; setsockopt(mySocket, SOL_SOCKET, SO_BINDTODEVICE, options, 4); printf("Descriptor: %i\n", mySocket); while(1) { pollStruct[0].fd = mySocket; pollStruct[0].events = POLLIN; pollStruct[0].revents = 0; if( poll(pollStruct, 1, 0) == 1) { printf("New Frame Arrived: "); uint16_t frameLength = recvfrom( mySocket, receiveBuffer_, 1536, 0, NULL, NULL); printf("Destination MAC: "); for ( uint8_t i = 0; i < 6; ++i ) { printf("0x%x ", receiveBuffer_[i]); } printf("\nSource MAC: "); for ( uint8_t i = 0; i < 6; ++i ) { printf("0x%x ", receiveBuffer_[i + 6]); } printf("\nEtherType: "); for ( uint8_t i = 0; i < 2; ++i ) { printf("0x%x ", receiveBuffer_[i + 12]); } printf("\nPayload: "); for ( uint32_t i = 14; i < frameLength; ++i ) { printf("0x%x ", receiveBuffer_[i]); } printf("\n"); //Clear buffer for ( uint32_t i = 0; i < frameLength; ++i ) receiveBuffer_[i] = 0; } } } 

我最初没有提到这个,但是我试图在Beaglebone Black上部署这个代码。 当我在一个使用GCC编译的Ubuntu的虚拟机上运行这个程序时,它就像我所期望的那样工作。 在接收/打印一个帧之后,该程序在视觉上空闲,直到新的一个到达。 当我交叉编译程序并运行程序时,程序会连续打印相同的数据包,直到新数据包到达。 因为每当recvfrom()返回的时候我都清除了receiverBuffer[] ,所以recvfrom()似乎并没有将内部缓冲区中的数据复制到缓冲区,因为它不断地复制数据。

我认为以下可能是一个原因*不设置轮询poll.1。它是actullay输出参数*超时使用一些正值。 如果你想要无限的等待时间使用-1。 请参阅投票人的页面