开发者

How to make socket.recv(500) not stop a while loop

I made an IRC bot which uses a while true loop to receive whatever is said.

To receive I use recv(500), but that stops the loop if there isn't anything to receive, but i need the loop to continue even if there isn't anything to receive.

I need a makeshift timer to continue running.

Example code:

/A lot of stuff/
timer=0
while 1:
    timer=timer+1
    line=s.开发者_JAVA百科recv(500) #If there is nothing to receive, the loop and thus the timer stop.
/A lot of stuff/

So either I need a way to stop it stopping the loop, or I need a better timer.


You can settimeout on the socket so that the call returns promptly (with a suitable exception, so you'll need a try/except around it) if nothing's there -- a timeout of 0.1 seconds actually works better than non-blocking sockets in most conditions.


This is going to prove a bad way to design a network application. I recommend looking into twisted, a networking library with an excellent implementation of the IRC protocol for making a client (like your bot) in twisted.words.protocols.irc.

http://www.habnabit.org/twistedex.html is an example of a very basic IRC bot written using twisted. With very little code, you are able to access a whole, correct, efficient, reconnecting implementation of IRC.

If you are intent on writing this from a socket level yourself, I still recommend studying a networking library like twisted to learn about how to effectively implement network apps. Your current technique will prove less effective than desired.


I usually use irclib which takes care of this sort of detail for you.


If you want to do this with low-level python, consider using the ready_sockets = select.select([s.fileno()], [], [], 0.1) -- this will test the socket s for readability. If your socket's file number is not returned in ready_sockets, then there is no data to read.

Be careful not to use the timout of "0" if you are going to call select repeatedly in a loop that does not otherwise yield the CPU -- that would consume 100% of the CPU as the loop executes. I gave 0.1 seconds timeout as an example; in this case, your timer variable would be counting tenths of a second.

Here's an example:

timer=0    
sockets_to_check = [s.fileno()]

while 1:
    ready_sockets = select.select(sockets_to_check, [], sockets_to_check, 0.1)
    if (len(ready_sockets[2]) > 0):
        # Handle socket error or closed connection here -- our socket appeared
        # in the 'exceptional sockets' return value so something has happened to 
        # it.
    elif (len(ready_sockets[0]) > 0):
        line = s.recv(500)
    else:
        timer=timer+1  # Note that timer is not incremented if the select did not
                       # incur a full 0.1 second delay.  Although we may have just
                       # waited for 0.09999 seconds without accounting for that.  If
                       # your timer must be perfect, you will need to implement it
                       # differently.  If it is used only for time-out testing, this 
                       # is fine.

Note that the above code takes advantage of the fact that your input lists contain only one socket. If you were to use this approach with multiple sockets, which select.select does support, the len(ready_sockets[x]) > 0 test would not reveal which socket is ready for reading or has an exception.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜