简体   繁体   English

将套接字从Python select的读取列表传递到另一个函数

[英]Passing a socket from Python select's read list into another function

I am using Python's select library to asynchronously read data off of two sockets. 我正在使用Python的select库从两个套接字异步读取数据。 Since the size of the packets that I receive can vary, and I don't know if there is a maximum possible size for the data that I am reading, I have implemented a function called recvAll(sock) to get all of the data off of a socket: 由于我接收到的数据包的大小可能会有所不同,并且我不知道读取的数据是否有最大可能的大小,因此我实现了一个称为recvAll(sock)的函数来获取所有数据插座的:

def recvAll(sock):
    buffer = ''
    data = []

    try:
        while True:
            buffer = sock.recv(8192)
            if not buffer:
                break
            data.append(buffer)
    except error, (errorCode, message):
        if errorCode != 10035:
            print 'error: ', str(errorCode), ' ', message
    return "".join(data)

I am calling the select library like this: 我这样调用选择库:

rlist, wlist, elist = select.select([sock1, sock2], [], [])
for sock in rlist:
    if sock == sock1:
        #data1 = sock.recv(8192)
        data1 = recvAll(sock)
    else:
        #data2 = sock.recv(8192)
        data2 = recvAll(sock)

In the for loop for each socket I process, if I call sock.recv directly, I am able to properly get data1 and data2. 在我处理的每个套接字的for循环中,如果直接调用sock.recv ,则可以正确获取data1和data2。 However, if I first pass sock to recvAll I am only able to get data1. 但是,如果我首先将sock传递给recvAll ,那么我只能获得data1。 It does not appear that recvAll is being called on sock2 at all. 它不会出现recvAll正在呼吁sock2可言。 Why is this the case? 为什么会这样呢?

Most likely what is going on is that, since your socket is not set as non-blocking ( socket.setblocking(0) ), your recvAll function is blocking, waiting for more input from the socket. 最可能的情况是,由于您的套接字未设置为非阻塞( socket.setblocking(0) ),因此您的recvAll函数正在阻塞,等待来自套接字的更多输入。 It won't return 0 until the socket is closed by the other end, or an error occurs. 直到另一端关闭套接字后,它才会返回0。

The way to fix this is to structure your code to combine the functions of recvAll with your select . 解决此问题的方法是构建代码,以将recvAll的功能与select结合起来。 Each time your select returns with an indication that there is data waiting on the socket, read from the socket ONLY ONCE, append the data to the buffer for that socket, then loop back into select . 每次您的select返回时,指示套接字上有数据等待,仅一次从套接字读取,将数据附加到该套接字的缓冲区中,然后循环回到select

After each recv , look at what you got and decide what to do next.. eg. 每次recv ,看看您得到了什么,然后决定下一步要做什么。 for some protocols, if the buffer contains a \\n , that would be an indication that you got a complete message and need to do something with it. 对于某些协议,如果缓冲区包含\\n ,则表明您已收到完整的消息,需要对其进行处理。 Or, in your case, it seems that closing of the socket is the indication that your message is complete.. so you should look for recv returning a zero length string.... 或者,在您的情况下,似乎套接字的关闭表明您的消息已完成..因此,您应查找返回零长度字符串的recv

If the socket was in fact closed, then you need to remove it from the list of sockets you are passing into select . 如果确实关闭了套接字,则需要将其从传递给select的套接字列表中删除。

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

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