1

I'm writing a function to read from socket and return exact size of data. And I thought of codes like:

whlie len(buf) < required:
    buf += socket.recv(required - len(buf))

return buf

But I think this might waste some CPU resources(not sure). I'm looking for a system call or something to return exact amount of data from socket, and it could be blocked until the required size is received.

3 Answers 3

2

This will not waste CPU resources.

sock.recv will block until at least one byte is available (but may buffer and return multiple bytes if they are available), so your application will not enter a busy loop.

In general, the buffer length of the sock.recv call should not have anything to do with the length of the message you'd like to retrieve.


String concatenation is not efficient for your buffer though.

You may want to consider using:

  • A list, and ''.join() (b''.join() if using Python 3)
  • The StringIO and cStringIO modules (or io.BytesIO if using Python 3).
  • Using sock.recv_into and StringIO / bytesIO .
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the note, I'm actually using bytearray type, dabeaz.blogspot.com/2010/01/few-useful-bytearray-tricks.html
StringIO and '' are out of place here, you want io.BytesIO or b''.
@phihag Thanks! I keep getting bit by Python 3! : )
socket.makefile is another solution.
0

If you are using the default socket library you can use the following.

import socket
host, port = "localhost", 8000
num_bytes  = 5000

sock = socket.socket()
sock.connect((host, port))
while True:
    data = sock.recv(num_bytes)
    handle(data)

You can take a look at the possible parameters here socket.recv documentation

1 Comment

This may not always work: num_bytes is the maximum number of bytes you will read, but may return less bytes than you intended to.
0

See my example for Python 2.x socket module. Use memoryview() and recv_into(),

def readReliably(s,n):
    buf = bytearray(n)
    view = memoryview(buf)
    sz = s.recv_into(view,n)
    return sz,buf

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
...
sz,buf = io.readReliably(s,4)
a = struct.unpack("4B",buf)
print repr(a)

Size of the buffer returned by readReliably() can be greater than n, don't forget about it.

Comments

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.