简体   繁体   English

注册和选择套接字究竟是如何工作的?

[英]How exactly does registering and selecting a socket work?

I'm learning some networking with Python.我正在使用 Python 学习一些网络。 While I find a lot of code samples, I don't find any explanations for some pieces of code.虽然我找到了很多代码示例,但我没有找到对某些代码的任何解释。 In the selectors module there seem to be two important functions, register and select.在选择器模块中似乎有两个重要的功能,寄存器和 select。 I can't find a good explanation on what exactly they do so I was hoping someone here could help.我找不到关于他们到底做了什么的很好的解释,所以我希望这里有人能提供帮助。

As an example I played around a bit with some sample code from the python documentation at https://docs.python.org/3/library/selectors.html . As an example I played around a bit with some sample code from the python documentation at https://docs.python.org/3/library/selectors.html . This code sample ends with此代码示例以

sel.register(sock, selectors.EVENT_READ, accept)

while True:
events = sel.select()
for key, mask in events:
    callback = key.data
    callback(key.fileobj, mask)

where "accept" is a function defined elsewhere in the code and "sel" is a selector.其中“accept”是代码中其他地方定义的 function,“sel”是选择器。 I've noticed that at first the select() call blocks the code until a connection is made by a client.我注意到一开始 select() 调用会阻塞代码,直到客户端建立连接。 But what exactly does it return?但它究竟返回了什么? From some experiments it seems to return a list with an item for each registered socket that got updated.从一些实验来看,它似乎返回一个列表,其中包含每个已更新的已注册套接字的项目。 But what is the "mask" variable?但是什么是“掩码”变量? In the python documentation it says that it is "a bitmask of events ready on this file object" , but I have no idea what this means and in my experiments it seems to be just the value 1.在 python 文档中,它说它是“此文件对象上准备好的事件的位掩码” ,但我不知道这意味着什么,在我的实验中它似乎只是值 1。

Also, when I replace the for-loop by "print(events)", I notice that once the socket gets used, the code no longer waits every time at sel.select().此外,当我将 for 循环替换为“print(events)”时,我注意到一旦使用了套接字,代码就不再每次都在 sel.select() 处等待。 Why is this?为什么是这样?

When registering a socket, I don't understand the data argument.注册套接字时,我不明白 data 参数。 The documentation just says it is an "opaque object" and it's None by default.文档只是说它是一个“不透明对象” ,默认情况下它是None Here it seems to be the function that should be called when a socket is used, but is this always the case?这里似乎是在使用套接字时应该调用的 function,但总是这样吗? And just to be clear, the selectors.EVENT_READ argument indicates that the socket can only receive information, not send it, right?为了清楚起见, selectors.EVENT_READ 参数表明套接字只能接收信息,不能发送信息,对吧?

Thanks in advance for your help!在此先感谢您的帮助!

I've noticed that at first the select() call blocks the code until a connection is made by a client.我注意到一开始 select() 调用会阻塞代码,直到客户端建立连接。

More accurately, it blocks until one or more of the registered sockets matches one of its registered events.更准确地说,它会阻塞,直到一个或多个已注册的 sockets 匹配其已注册的事件之一。 So, in your example, select() will block indefinitely (since you are not specifying a value for the timeout parameter) until sock reports the EVENT_READ event is ready.因此,在您的示例中, select()将无限期地阻塞(因为您没有为timeout参数指定值),直到sock报告EVENT_READ事件已准备好。

But what exactly does it return?但它究竟返回了什么? From some experiments it seems to return a list with an item for each registered socket that got updated.从一些实验来看,它似乎返回一个列表,其中包含每个已更新的已注册套接字的项目。 But what is the "mask" variable?但是什么是“掩码”变量?

This is answered in the same document you linked to:这在您链接到的同一文档中得到了回答:

This returns a list of (key, events) tuples , one for each ready file object.这将返回一个(key, events)元组列表,每个准备好的文件 object 一个。

key is the SelectorKey instance corresponding to a ready file object. key是对应准备好的文件 object 的SelectorKey实例。 events is a bitmask of events ready on this file object. events是此文件 object 上准备好的事件的位掩码。

In the python documentation it says that it is "a bitmask of events ready on this file object", but I have no idea what this means在 python 文档中它说它是“在这个文件对象上准备好的事件的位掩码”,但我不知道这意味着什么

You can register multiple events for a socket.您可以为一个套接字注册多个事件。 The reported mask will tell you which of those events is actually ready.报告的mask将告诉您哪些事件实际上已准备好。

and in my experiments it seems to be just the value 1.在我的实验中,它似乎只是值 1。

That is the numeric value for EVENT_READ .这是EVENT_READ的数值。 That is the only value you are getting, because that is the only event you are registering.这是您获得的唯一价值,因为这是您注册的唯一事件。 But there are other events you can register, such as EVENT_WRITE .但是您可以注册其他事件,例如EVENT_WRITE

Also, when I replace the for-loop by "print(events)", I notice that once the socket gets used, the code no longer waits every time at sel.select().此外,当我将 for 循环替换为“print(events)”时,我注意到一旦使用了套接字,代码就不再每次都在 sel.select() 处等待。 Why is this?为什么是这样?

Because you are not calling your accept() function anymore to read data from the socket.因为您不再调用您的accept() function 来从套接字读取数据。 The socket will remain in a readable state as long as it has pending data waiting to be read.只要套接字有等待读取的待处理数据,套接字就会保留在可读的 state 中。 Thus your select() will continue to report that EVENT_READ is ready for the socket until all of its pending data has been read.因此,您的select()将继续报告EVENT_READ已为套接字做好准备,直到其所有未决数据已被读取。

When registering a socket, I don't understand the data argument.注册套接字时,我不明白 data 参数。

It is whatever you want it to be.它是你想要的任何东西。 You can associate whatever custom data you want with your event registrations, and then select() will give that data back to you each time an event is reported.您可以将所需的任何自定义数据与事件注册相关联,然后select()将在每次报告事件时将该数据返回给您。

The documentation just says it is an "opaque object" and it's None by default.文档只是说它是一个“不透明对象”,默认情况下它是 None 。 Here it seems to be the function that should be called when a socket is used, but is this always the case?这里似乎是在使用套接字时应该调用的 function,但总是这样吗?

No. It can be whatever you need it to be.不,它可以是你需要的任何东西。

And just to be clear, the selectors.EVENT_READ argument indicates that the socket can only receive information, not send it, right?为了清楚起见, selectors.EVENT_READ 参数表明套接字只能接收信息,不能发送信息,对吧?

No. It means that you are interested in being notified only when the socket is in a readable state.不。这意味着您有兴趣仅在套接字位于可读的 state 时收到通知。 You can always write to a socket, at least until shutdown(SHUT_WR) or close() is called on it.您始终可以写入套接字,至少在对其调用shutdown(SHUT_WR)close()之前。 For a non-blocking socket, send() can fail if it would block (because the receiver's buffer is full), in which case you would have to wait for EVENT_WRITE to be ready on the socket (the receiver is ready to receive more data) before you can send data on that socket again.对于非阻塞套接字,如果send()阻塞(因为接收器的缓冲区已满),它可能会失败,在这种情况下,您必须等待套接字上的EVENT_WRITE准备好(接收器已准备好接收更多数据) 在您可以再次在该套接字上发送数据之前。

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

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