简体   繁体   English

Linux Networking IO Noob:Select()和Recvfrom,是阻塞还是非阻塞?

[英]Linux Networking IO Noob: Select() and Recvfrom, Blocking or Non-blocking?

I inherited a piece of code that reads in data from a UDP socket. 我继承了一段从UDP套接字读取数据的代码。 I need some help figuring out what's going on here and also if I can improve anything performance wide. 我需要一些帮助来弄清楚这里发生了什么,以及是否可以提高整个性能。

The code starts by calling select(), and then recvfrom(). 该代码首先调用select(),然后调用recvfrom()。 Based on my research, it appears that recvfrom() is only called when select() returns the fact that there is data available. 根据我的研究,看来只有在select()返回有可用数据的事实时才调用recvfrom()。 This code basically consists of a thread that continuously listens for a multicast message. 这段代码基本上由一个连续侦听多播消息的线程组成。 As a result, it basically sits in the select() routine until it either receives data or times out. 结果,它基本上位于select()例程中,直到它接收数据或超时。

I was wondering if there was perhaps a better way to improve upon the performance of this code. 我想知道是否有更好的方法来改善此代码的性能。 First, is select() necessary? 首先,select()是否必要? Based on this thread: setting timeout for recv fcn of a UDP socket it appears that I can just set the timeout of the recvfrom() command itself. 基于此线程: 为UDP套接字的recv fcn设置超时,看来我可以直接设置recvfrom()命令本身的超时。 Will this buy me anything? 这会给我买什么吗? Also, based on some research, I've seen alot of implementations without select(). 另外,基于一些研究,我看到了很多没有select()的实现。 Why is this? 为什么是这样?

Also, ideally, I'd like to free up as much CPU as possible. 另外,理想情况下,我想释放尽可能多的CPU。 Is there a way that I can put the process to sleep until it receives a packet? 有没有办法让我的进程进入休眠状态,直到它收到一个数据包? That being said, I'd like to receive a full packet at a time for simplicity sake. 话虽如此,为简单起见,我想一次接收一个完整的数据包。

Thanks in advance for the help. 先谢谢您的帮助。

When recvfrom blocks or when select is waiting for an event, the process is effectively asleep; recvfrom块或select正在等待事件时,该过程实际上处于睡眠状态。 that is, it is not scheduled to run. 也就是说,它没有计划运行。 So your existing code (at least if I'm interpreting your description correctly) already satisfies your first requirement. 因此,您现有的代码(至少在我正确解释了您的描述的情况下)已经满足您的第一个要求。

Is there a way that I can put the process to sleep until it receives a packet? 有没有办法让我的进程进入休眠状态,直到它收到一个数据包?

UDP is a "datagram packet service". UDP是一种“数据报包服务”。 (Quoted from man 7 udp ). (引自man 7 udp )。 That is, it always sends and receives complete packets. 也就是说,它总是发送和接收完整的数据包。 So with UDP, you never have to worry about your second requirement: 因此,使用UDP,您不必担心第二个要求:

I'd like to receive a full packet at a time for simplicity sake. 为了简单起见,我希望一次接收一个完整的数据包。

All in all, I'd say you don't have a problem. 总而言之,我想你没问题。

However, you may be able to remove the select() call, if it is only waiting on a single descriptor, assuming you are able to setsocketopt() SO_RCVTIMEO (which you probably can do, although Posix allows an individual implementation to not allow the option to be set, so there is no absolute guarantee.) I doubt whether you will notice any performance improvement from doing so, but it should save a few microseconds. 但是,您可能能够删除的select()调用,如果只在一个单一的描述等,假设你是能够setsocketopt() SO_RCVTIMEO (你也许可以做到,虽然Posix的允许个人实施不允许选项设置,因此没有绝对的保证。)我怀疑您是否会注意到这样做带来的性能改进,但是应该节省几微秒。

Is there a way that I can put the process to sleep until it receives a packet? 有没有办法让我的进程进入休眠状态,直到它收到一个数据包?

You're already doing that. 您已经在这样做了。 That's what select() does, or recvfrom() in blocking mode. 那就是select()所做的,或者是在阻塞模式下的recvfrom()。

I'd like to receive a full packet at a time for simplicity sake. 为了简单起见,我希望一次接收一个完整的数据包。

That's what UDP is already doing for you. 这就是UDP已经为您完成的工作。

可能会有所帮助: 10k问题

I can just set the timeout of the recvfrom() command itself

If select waits on only one file descriptor (eg socket), then there would be not much difference with what you propose. 如果select仅在一个文件描述符(例如套接字)上等待,则与您的建议没有太大区别。 But if this manages more than one, then there isn't really a better solution to this. 但是,如果这管理多个,则实际上没有更好的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM