17

I need to empty the data on a socket (making sure that there is nothing to receive). Unfortunately, there is no function for this in the python socket module.

I've implemented something this way:

def empty_socket(sock):
    """remove the data present on the socket"""
    input = [sock]
    while 1:
        inputready, o, e = select.select(input,[],[], 0.0)
        if len(inputready)==0: break
        for s in inputready: s.recv(1)

What do you think? Is there a better way to do that?


Update: I don't want to change the socket timeout. What's why i prefer a select to a read.


Update: The original question was using the 'flush' term. It seems that 'empty' is a better term.


Update - 2010-02-27 : I've noticed a bug when the pair has closed. The inputready is always filled with the sockets. I fixed that by adding a maximum number of loops. Is there a better fix?

4
  • this isn't really a "flush" per say. Take a look at the examples in the documentation for reading a socket. docs.python.org/library/socket.html#example Commented Jul 8, 2009 at 13:33
  • 1
    Have you considered using Twisted for your program instead? If you did, you'd never need to do anything like this. Twisted will immediately pull all the data out of the socket and deliver it to you whenever any arrives, so you don't need to mess about with ugly details like the select() problem described by Thomas's answer below. Commented Jul 9, 2009 at 11:19
  • 1
    @Glyph: No I didn't consider Twisted because I wanted to use the standard python module in order to avoid external dependencies. Thanks for this comment, I will look at Twisted and maybe reconsider my choice Commented Jul 9, 2009 at 11:42
  • A friend told me to look at Twisted. After many struggles, I will try that next. It would be good if all the bad examples of python networking would just go away. Commented Aug 14, 2023 at 23:19

5 Answers 5

9

If by "flush" you mean throw away any pending incoming data then you can either use select() like you do, or set the socket to nonblocking and read in a loop until you're out of data.

Also note that (from the Linux manpage):

Under Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may be safer to use O_NONBLOCK on sockets that should not block.

Spurious readiness notification for Select System call

And as has been noted by others, "flush" usually refers to output.

Sign up to request clarification or add additional context in comments.

4 Comments

What would be the right term for "flushing" an input? Thanks for your answer
Personally, I would call what you're doing "emptying" the socket. Although it does seem strange to me why you would want to do this - somebody sent you that data for a reason, why are you throwing it all away without processing it? :)
cant we just do a recv with len to read as 0 after select returns?
I believe drain is the normal term
5

Using select.select is good practice, as indicated in the Socket Programming HOWTO. You'll need to set the socket as non-blocking, using sock.setblocking(0).

Just a comment about nomenclature: flush is normally associated with output operations.

Comments

1

For UDP packets, I did the following:

  1. After creating the socket, setting options, and binding, I use socket.settimeout(). Note the documentation for setblocking() gives some information which that of settimeout() doesn't - if you want your socket operations to block, you should just use settimeout() to set the timeout. setblocking() just puts an infinite timeout on it. (I had a bug calling settimeout() followed by setblocking(1).)

  2. My "buffer emptying" function is then just this ("Listener" is my socket):

    def FlushListen(self): while 1: try: PacketBytes = self.__Listener.recv(1024) except: break;

    With a timeout of 1 second, this will read all the UDP packets and then return 1 second after there's no data.

In my case I'm using it to just talk between two programs on the same PC so I could easily lower my timeout but speed is not an issue so I'm fine with this.

According to some of the links others posted, this should work with data streams as well.

Comments

0

Cant we just keep on reading until buffer is empty?

def clear_buffer(sock):
    try:
        while sock.recv(1024): pass
    except:
        pass

Comments

-1

Not sure if this will work, but you could attach a file object to the socket's file descriptor and call the flush() method on that file object:

import os

file_obj = os.fdopen(your_socket.fileno())
file_obj.flush()

This won't work in Windows because the descriptor returned by fileno() can't be passed to os.fdopen() in Windows

1 Comment

flush on file objects only flushes the output cached in userspace. Compare FILE* in C and fflush. Raw socket I/O is usually not buffered, and if it is then it's not buffered in userspace, and a fflush-like operation will not work. You may want to look at "push" for TCP.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.