473,491 Members | 1,965 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Receive data from socket stream

I wanted to ask for standard ways to receive data from a socket stream
(with socket.socket.recv()). It's simple when you know the amount of
data that you're going to receive, or when you'll receive data until
the remote peer closes the connection. But I'm not sure which is the
best way to receive a message with undetermined length from a stream
in a connection that you expect to remain open. Until now, I've been
doing this little trick:

data = client.recv(256)
new = data
while len(new) == 256:
new = client.recv(256)
data += new

That works well in most cases. But it's obviously error-prone. What if
the client sent *exactly* two hundred and fifty six bytes? It would
keep waiting for data inside the loop. Is there really a better and
standard way, or is this as best as it gets?

Sorry if this is a little off-topic and more related to networking,
but I'm using Python anyway.

Thanks,
Sebastian
Jun 27 '08 #1
16 7518
s0****@gmail.com wrote:
I wanted to ask for standard ways to receive data from a socket stream
(with socket.socket.recv()). It's simple when you know the amount of
data that you're going to receive, or when you'll receive data until
the remote peer closes the connection. But I'm not sure which is the
best way to receive a message with undetermined length from a stream
in a connection that you expect to remain open. Until now, I've been
doing this little trick:

data = client.recv(256)
new = data
while len(new) == 256:
new = client.recv(256)
data += new

That works well in most cases. But it's obviously error-prone. What if
the client sent *exactly* two hundred and fifty six bytes? It would
keep waiting for data inside the loop. Is there really a better and
standard way, or is this as best as it gets?

Sorry if this is a little off-topic and more related to networking,
but I'm using Python anyway.
You solve this by having a protocol that the client and server both
agree on, so that the client knows how much to read from the server.
There are any number of ways of doing this, all of which depend on the
kind of data you want to transfer and for what purpose.

--
Erik Max Francis && ma*@alcyone.com && http://www.alcyone.com/max/
San Jose, CA, USA && 37 18 N 121 57 W && AIM, Y!M erikmaxfrancis
In the final choice a solider's pack is not so heavy a burden as a
prisoner's chains. -- Dwight D. Eisenhower, 1890-1969
Jun 27 '08 #2
On Apr 25, 5:52*pm, Erik Max Francis <m...@alcyone.comwrote:
s0s...@gmail.com wrote:
I wanted to ask for standard ways to receive data from a socket stream
(with socket.socket.recv()). It's simple when you know the amount of
data that you're going to receive, or when you'll receive data until
the remote peer closes the connection. But I'm not sure which is the
best way to receive a message with undetermined length from a stream
in a connection that you expect to remain open. Until now, I've been
doing this little trick:
data = client.recv(256)
new = data
while len(new) == 256:
* * new = client.recv(256)
* * data += new
That works well in most cases. But it's obviously error-prone. What if
the client sent *exactly* two hundred and fifty six bytes? It would
keep waiting for data inside the loop. Is there really a better and
standard way, or is this as best as it gets?
Sorry if this is a little off-topic and more related to networking,
but I'm using Python anyway.

You solve this by having a protocol that the client and server both
agree on, so that the client knows how much to read from the server.
There are any number of ways of doing this, all of which depend on the
kind of data you want to transfer and for what purpose.

--
Erik Max Francis && m...@alcyone.com &&http://www.alcyone.com/max/
* San Jose, CA, USA && 37 18 N 121 57 W && AIM, Y!M erikmaxfrancis
* *In the final choice a solider's pack is not so heavy a burden as a
* * prisoner's chains. -- Dwight D. Eisenhower, 1890-1969
So, in an HTTP client/server, I'd had to look in a Content-Length
header?
Jun 27 '08 #3
On Apr 25, 7:39*pm, s0s...@gmail.com wrote:
I wanted to ask for standard ways to receive data from a socket stream
(with socket.socket.recv()). It's simple when you know the amount of
data that you're going to receive, or when you'll receive data until
the remote peer closes the connection. But I'm not sure which is the
best way to receive a message with undetermined length from a stream
in a connection that you expect to remain open. Until now, I've been
doing this little trick:

data = client.recv(256)
new = data
while len(new) == 256:
* * new = client.recv(256)
* * data += new

That works well in most cases. But it's obviously error-prone. What if
the client sent *exactly* two hundred and fifty six bytes? It would
keep waiting for data inside the loop. Is there really a better and
standard way, or is this as best as it gets?

Sorry if this is a little off-topic and more related to networking,
but I'm using Python anyway.

Thanks,
Sebastian

done = False
remaining = ''
while done == False:
data = client.recv(256)
done, remaining = process(remaining + data)

PS: are you sure you shouldn't be using RPC or SOAP ?
Jun 27 '08 #4
s0****@gmail.com wrote:
Until now, I've been
doing this little trick:

data = client.recv(256)
new = data
while len(new) == 256:
new = client.recv(256)
data += new
Are you aware that recv() will not always return the amount of bytes asked for?
(send() is similar; it doesn't guarantee that the full buffer you pass to it will be
sent at once)

I suggest reading this: http://www.amk.ca/python/howto/sockets/sockets.html
--irmen
Jun 27 '08 #5
On Apr 26, 7:25 am, Irmen de Jong <irmen.NOS...@xs4all.nlwrote:
s0s...@gmail.com wrote:
Until now, I've been
doing this little trick:
data = client.recv(256)
new = data
while len(new) == 256:
new = client.recv(256)
data += new

Are you aware that recv() will not always return the amount of bytes asked for?
(send() is similar; it doesn't guarantee that the full buffer you pass to it will be
sent at once)

I suggest reading this:http://www.amk.ca/python/howto/sockets/sockets.html

--irmen
So every time I use I want to send some thing, I must use

totalsent = 0
while sent < len(data):
sent = sock.send(data[totalsent:])
totalsent += sent

instead of a simple sock.send(data)? That's kind of nasty. Also, is it
better then to use sockets as file objects? Maybe unbuffered?
Jun 27 '08 #6

<s0****@gmail.comwrote in message
news:4c**********************************@56g2000h sm.googlegroups.com...
On Apr 26, 7:25 am, Irmen de Jong <irmen.NOS...@xs4all.nlwrote:
>s0s...@gmail.com wrote:
Until now, I've been
doing this little trick:
data = client.recv(256)
new = data
while len(new) == 256:
new = client.recv(256)
data += new

Are you aware that recv() will not always return the amount of bytes
asked for?
(send() is similar; it doesn't guarantee that the full buffer you pass to
it will be
sent at once)

I suggest reading
this:http://www.amk.ca/python/howto/sockets/sockets.html

--irmen

So every time I use I want to send some thing, I must use

totalsent = 0
while sent < len(data):
sent = sock.send(data[totalsent:])
totalsent += sent

instead of a simple sock.send(data)? That's kind of nasty. Also, is it
better then to use sockets as file objects? Maybe unbuffered?
I think you meant:

while totalsent < len(data):

Python also has the sendall() function.

-Mark

Jun 27 '08 #7
s0****@gmail.com <s0****@gmail.comwrote:
I wanted to ask for standard ways to receive data from a socket stream
(with socket.socket.recv()). It's simple when you know the amount of
data that you're going to receive, or when you'll receive data until
the remote peer closes the connection. But I'm not sure which is the
best way to receive a message with undetermined length from a stream
in a connection that you expect to remain open. Until now, I've been
doing this little trick:

data = client.recv(256)
new = data
while len(new) == 256:
new = client.recv(256)
data += new

That works well in most cases. But it's obviously error-prone. What if
the client sent *exactly* two hundred and fifty six bytes? It would
keep waiting for data inside the loop. Is there really a better and
standard way, or is this as best as it gets?
What you are missing is that if the recv ever returns no bytes at all
then the other end has closed the connection. So something like this
is the correct thing to write :-

data = ""
while True:
new = client.recv(256)
if not new:
break
data += new

From the man page for recv

RETURN VALUE

These calls return the number of bytes received, or -1 if an
error occurred. The return value will be 0 when the peer has
performed an orderly shutdown.

In the -1 case python will raise a socket.error.

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Jun 27 '08 #8
Mark Tolonen <M8********@mailinator.comwrote:
So every time I use I want to send some thing, I must use

totalsent = 0
while sent < len(data):
sent = sock.send(data[totalsent:])
totalsent += sent

instead of a simple sock.send(data)? That's kind of nasty. Also, is it
better then to use sockets as file objects? Maybe unbuffered?

I think you meant:

while totalsent < len(data):

Python also has the sendall() function.
Just to elaborate, sendall does exactly the above for you.

sendall(self, *args)
sendall(data[, flags])

Send a data string to the socket. For the optional flags
argument, see the Unix manual. This calls send() repeatedly
until all data is sent. If an error occurs, it's impossible
to tell how much data has been sent.

There should really be a recvall for symmetry, but I don't think it
would get much use!

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Jun 27 '08 #9
Nick Craig-Wood <ni**@craig-wood.comwrites:
What you are missing is that if the recv ever returns no bytes at all
then the other end has closed the connection. So something like this
is the correct thing to write :-

data = ""
while True:
new = client.recv(256)
if not new:
break
data += new
This is a good case for the iter() function:

buf = cStringIO.StringIO()
for new in iter(partial(client.recv, 256), ''):
buf.write(new)
data = buf.getvalue()

Note that appending to a string is almost never a good idea, since it
can result in quadratic allocation.
Jun 27 '08 #10
Hrvoje Niksic <hn*****@xemacs.orgwrote:
Nick Craig-Wood <ni**@craig-wood.comwrites:
What you are missing is that if the recv ever returns no bytes at all
then the other end has closed the connection. So something like this
is the correct thing to write :-

data = ""
while True:
new = client.recv(256)
if not new:
break
data += new

This is a good case for the iter() function:

buf = cStringIO.StringIO()
for new in iter(partial(client.recv, 256), ''):
buf.write(new)
data = buf.getvalue()

Note that appending to a string is almost never a good idea, since it
can result in quadratic allocation.
My aim was clear exposition rather than the ultimate performance!

Anyway str += was optimised in python 2.4 or 2.5 (forget which) wasn't
it? I'm not convinced it will be any worse performing than
cStringIO.StringIO.write() which effectively appends to a string in
exactly the same way.

This test agrees with me!

$ python -m timeit -s 's = ""' 'for i in xrange(100000): s+="x"'
10 loops, best of 3: 23.8 msec per loop

$ python -m timeit -s 'from cStringIO import StringIO; s=StringIO()' 'for i in xrange(100000): s.write("x")'
10 loops, best of 3: 56 msec per loop

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Jun 27 '08 #11
On Apr 28, 4:30 am, Nick Craig-Wood <n...@craig-wood.comwrote:
s0s...@gmail.com <s0s...@gmail.comwrote:
I wanted to ask for standard ways to receive data from a socket stream
(with socket.socket.recv()). It's simple when you know the amount of
data that you're going to receive, or when you'll receive data until
the remote peer closes the connection. But I'm not sure which is the
best way to receive a message with undetermined length from a stream
in a connection that you expect to remain open. Until now, I've been
doing this little trick:
data = client.recv(256)
new = data
while len(new) == 256:
new = client.recv(256)
data += new
That works well in most cases. But it's obviously error-prone. What if
the client sent *exactly* two hundred and fifty six bytes? It would
keep waiting for data inside the loop. Is there really a better and
standard way, or is this as best as it gets?

What you are missing is that if the recv ever returns no bytes at all
then the other end has closed the connection. So something like this
is the correct thing to write :-

data = ""
while True:
new = client.recv(256)
if not new:
break
data += new

From the man page for recv

RETURN VALUE

These calls return the number of bytes received, or -1 if an
error occurred. The return value will be 0 when the peer has
performed an orderly shutdown.

In the -1 case python will raise a socket.error.

--
Nick Craig-Wood <n...@craig-wood.com--http://www.craig-wood.com/nick
But as I said in my first post, it's simple when you know the amount
of data that you're going to receive, or when you'll receive data
until the remote peer closes the connection. But what about receiving
a message with undetermined length in a connection that you don't want
to close? I already figured it out: in the case of an HTTP server/
client (which is what I'm doing), you have to look for an empty line
in the message, which signals the end of the message headers. As for
the body, you have to look at the Content-Length header, or, if the
message body contains the "chunked" transfer-coding, you have to
dynamically decode the encoding. There are other cases but those are
the most influent.

BTW, has anybody used sockets as file-like objects
(client.makefile())? Is it more secure? More efficient?

Sebastian
Jun 27 '08 #12
Nick Craig-Wood <ni**@craig-wood.comwrites:
> Note that appending to a string is almost never a good idea, since it
can result in quadratic allocation.

My aim was clear exposition rather than the ultimate performance!
That would normally be fine. My post wasn't supposed to pick
performance nits, but to point out potentially quadratic behavior.
Anyway str += was optimised in python 2.4 or 2.5 (forget which) wasn't
it?
That optimization works only in certain cases, when working with
uninterned strings with a reference count of 1, and then only when the
strings are in stored local variables, rather than in global vars or
in slots. And then, it only works in CPython, not in other
implementations. The optimization works by "cheating" -- breaking the
immutable string abstraction in the specific cases in which it is
provably safe to do so.
http://utcc.utoronto.ca/~cks/space/b...tringConcatOpt
examines it in some detail.

Guido was reluctant to accept the patch that implements the
optimization because he thought it would "change the way people write
code", a sentiment expressed in
http://mail.python.org/pipermail/pyt...st/046702.html
This discussion shows that he was quite right in retrospect. (I'm not
saying that the optimization is a bad thing, just that it is changing
the "recommended" way of writing Python in a way that other
implementations cannot follow.)
Jun 27 '08 #13
On Apr 28, 4:42 am, Hrvoje Niksic <hnik...@xemacs.orgwrote:
Nick Craig-Wood <n...@craig-wood.comwrites:
What you are missing is that if the recv ever returns no bytes at all
then the other end has closed the connection. So something like this
is the correct thing to write :-
data = ""
while True:
new = client.recv(256)
if not new:
break
data += new

This is a good case for the iter() function:

buf = cStringIO.StringIO()
for new in iter(partial(client.recv, 256), ''):
buf.write(new)
data = buf.getvalue()

Note that appending to a string is almost never a good idea, since it
can result in quadratic allocation.
A question regarding cStringIO.StringIO(): is there a way to do get
getvalue() to return all the bytes after the current file position
(not before)? For example

buf = cStringIO.StringIO()
buf.write("foo bar")
buf.seek(3)
buf.getvalue(True) # the True argument means
# to return the bytes up
# to the current file position

That returns 'foo'. Is there a way to get it to return ' bar'?
Jun 27 '08 #14
En Mon, 28 Apr 2008 19:29:33 -0300, <s0****@gmail.comescribió:
A question regarding cStringIO.StringIO(): is there a way to do get
getvalue() to return all the bytes after the current file position
(not before)? For example

buf = cStringIO.StringIO()
buf.write("foo bar")
buf.seek(3)
buf.getvalue(True) # the True argument means
# to return the bytes up
# to the current file position

That returns 'foo'. Is there a way to get it to return ' bar'?
buf.read() - the obvious answer, once you know it :)

--
Gabriel Genellina

Jun 27 '08 #15
Hrvoje Niksic <hn*****@xemacs.orgwrote:
Nick Craig-Wood <ni**@craig-wood.comwrites:
Note that appending to a string is almost never a good idea, since it
can result in quadratic allocation.
My aim was clear exposition rather than the ultimate performance!

That would normally be fine. My post wasn't supposed to pick
performance nits, but to point out potentially quadratic behavior.
Anyway str += was optimised in python 2.4 or 2.5 (forget which) wasn't
it?

That optimization works only in certain cases, when working with
uninterned strings with a reference count of 1, and then only when the
strings are in stored local variables, rather than in global vars or
in slots. And then, it only works in CPython, not in other
implementations. The optimization works by "cheating" -- breaking the
immutable string abstraction in the specific cases in which it is
provably safe to do so.
http://utcc.utoronto.ca/~cks/space/b...tringConcatOpt
examines it in some detail.
Ah, I didn't realise that - thanks for the interesting link.

For the example I gave, just a simple local variable the optimisation
kicks in. I can see how you could easily migrate that to an instance
variable and the optimisation would no longer work, eg

$ python -m timeit -s 's=""' 'for i in xrange(10000): s+="x"'
1000 loops, best of 3: 1.04 msec per loop

$ python -m timeit -s 'class A: pass' -s 'a=A(); a.s=""' 'for i in xrange(10000): a.s+="x"'
10 loops, best of 3: 160 msec per loop
Guido was reluctant to accept the patch that implements the
optimization because he thought it would "change the way people write
code", a sentiment expressed in
http://mail.python.org/pipermail/pyt...st/046702.html
This discussion shows that he was quite right in retrospect. (I'm not
saying that the optimization is a bad thing, just that it is changing
the "recommended" way of writing Python in a way that other
implementations cannot follow.)
Certainly something I wasn't aware of before - thanks!

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Jun 27 '08 #16
s0****@gmail.com <s0****@gmail.comwrote:
But as I said in my first post, it's simple when you know the amount
of data that you're going to receive, or when you'll receive data
until the remote peer closes the connection. But what about receiving
a message with undetermined length in a connection that you don't want
to close?
You obviously need some sort of protocol. Here is some code (taken
from a real project and modified a bit) which returns \r\n seperated
lines from a socket as they arrive which is a very simple (but
widespread) protocol.

self.rx_buf is set to "" in the initialisation
self.sock is the socket

def rx_line(self):
message = None
while 1:
pos = self.rx_buf.find("\r\n")
if pos >= 0:
message = self.rx_buf[:pos]
self.rx_buf = self.rx_buf[pos+2:]
break
try:
rx = self.sock.recv(4096)
except socket.error, e:
self.sock = None
raise ServerNetworkException(e)
if len(rx) == 0:
self.sock = None
raise ServerDisconnectedException()
self.rx_buf += rx
return message

Sorry I mis-understood your original post!

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Jun 27 '08 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
5354
by: Kitchen Bin | last post by:
Hi. I am trying to use Sockets to do multiple Send and Receives via HTTP (not simultaneously). A first pair of Send/Receives works fine and sure enough I receive HTML back, but the next...
0
4178
by: ?lafur Helgi R?gnvaldsson | last post by:
I'm building a server application which accepts socket connections and I ran into some problems. The socket is asynchronous and therefore uses the BeginXXX and EndXXX methods in the Socket class...
2
10084
by: Craig | last post by:
Hi I listen on a port, when data is received I raise an event (OnMessageReceived) in the while loop as follows: private void WaitForConnection() { TcpListener listener = new...
0
1161
by: whetham63 | last post by:
When I run this on my network at home and on my network at work it runs fine. When this is run at a clients network I am receiving a after the first packet is received(There are 2 packets...
1
3807
by: Saso Zagoranski | last post by:
Hi! I have simple client/server game that uses sockets to transfer different messages. The server and the client are running on the same machine.
2
2711
by: Qindong Zhang | last post by:
My socket application blocked at socket.receiver() after received all information from sender. Should socket.Receive() return 0 after no more data available? Note: My socket object was not close on...
6
2071
by: Simon Says | last post by:
Hi all, I've a message object that is serialized to a xml string and communicating between a client and server with a connection-oriented (TCP) socket. Unlike a UDP, in a TCP socket, the...
3
3598
by: Joe Blauth | last post by:
Hi all, I am currently working on a small application that sends messages from a client to a server and receives messages in return. Basically the functionality is made with sockets which is...
4
11229
by: danomano | last post by:
The code below works fine. As of now I just set the buffer length real big and all is good. However, I hate the impreciseness of that. So my question in general is how do I know what length to...
0
6980
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7192
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
6862
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7364
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5452
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
4579
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3087
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
1397
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
282
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.