I need to write a client that uses raw sockets. The client
authenticates to the server and a persistent TCP connection is
established. Occasionally the server transmits a small amount of data
on that connection, which I then read via the client and then act on
the resulting data.
What I'd normally do is just write this using Python's standard
sockets library and then have the app sit in a loop, reading from the
input buffer when data was present. However, it would be cleaner if I
could use an async design instead that used callbacks rather than a
loop.
Would gevent be a good library for this? If so, could someone point
me at some sample code that might be handy? Thanks!
http://bitbucket.org/denis/gevent/src/tip/examples/echoserver.py
--
С уважением, Андрей Попп.
+7 911 740 24 91
You probably need first to study python socket module
(http://docs.python.org/library/socket.html) or better to read book
UNIX programming (http://www.kohala.com/start/unpv12e.html).
gevent.socket module mimics standard python socket module, but
provides non-blocking version of it, so there is no difference in
using them.
In this application, does gevent offer any real advantages to just
using standard sockets or asyncore?
> echoclient.py
> < 1KViewDownload
import gevent
import gevent.socket
import socket
def client():
s = gevent.socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('66.102.7.147', 80))
s.send('GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n')
block = s.recv(65536)
while block:
print block
block = s.recv(65536)
s.close()
g = gevent.spawn(client)
g.join()
Say you wanted to write a silly HTTP load tester. Take that call to spawn()
and wrap it in a loop. Put the result of all those calls to spawn() into a
list and then call gevent.joinall(). Now you've got a client app that can do
thousands of HTTP connections in parallel and, if you're careful with
python, gigabits of traffic (yes, plural, I'm doing it right now). All from
a single machine and a single CPU.
What happens under the covers is that when a call needs to block, like
connect, send and recv, that file descriptor is put onto a list to be
watched until it is ready. Once on this list your green thread (in this case
the client function) is context switched out and another thread is allowed
to run.
There are several wonderful things about this programming model. First, the
threads that get created are very light weight. They involve little more
overhead than the stack frame that contains them. They're way lighter than
normal threads and, though bound to a single CPU, allow you to create
thousands upon thousands of them without destroying your machine.
The second wonderful thing about this programming model is that
synchronization becomes a thing of the past. Because a green thread never
gets swapped out at just the wrong time you don't need to lock access to
shared state. No two threads can ever run at the same time.
Perhaps the third wonderful thing is that you still get to use the thread
abstraction that the human mind is capable of understanding. It's all
self-contained and the flow is from top to bottom without much fanfare. You
program as though you only had a single thread even though you might have
thousands.
-Bob
g = gevent.spawn(client)
g.join()
print "Hello!"
"Hello!" isn't printed unless an exception is thrown in "client".
> On 2/27/10 2:21 PM, "Jamie" <jjbe...@gmail.com> wrote:
>
> > I guess the basic question that I have is: How do I set up a callback
> > handler that will process the replies from the server? As an example,
> > here is how the asyncore module does it:
>
> http://docs.python.org/library/asyncore.html#asyncore-example-basic-h...>
> >>>> Ñ óâàæåíèåì, Àíäðåé Ïîïï.
> >>>> +7 911 740 24 91
>
> >> --
> >> Ñ óâàæåíèåì, Àíäðåé Ïîïï.
I'm not getting any exceptions.
-Bob
On Feb 27, 9:54 pm, Bob Van Zant <b...@veznat.com> wrote:
> I should note that I don't have this same problem. When I put the print
> statement after the join() "Hello!" is printed after the HTTP GET request
> finishes. Which is what I'd expect.
>
> I'm not getting any exceptions.
>
> -Bob
>
Easy way to find those out, add this line at the beginning of your
script:
import gevent; print gevent.__version__, gevent.core.get_version()