On Mon, 29 Aug 2005 21:30:51 +0200, Michael Goettsche <[EMAIL PROTECTED]> wrote:
>Hi there,
>
>I'm trying to write a simple server/client example. The client should be able
>to send text to the server and the server should distribute the text to all
>connected clients. However, it seems that only the first entered text is sent
>and received. When I then get prompted for input again and press return,
>nothing gets back to me. Any hints on what I have done would be very much
>appreciated!

You aren't handling readiness notification properly.  Twisted is a good way to 
not have to deal with all the niggling details of readiness notification.  I 
haven't trotted out this example in a while, and it's /almost/ appropriate here 
;) so...

http://www.livejournal.com/users/jcalderone/2660.html

Of course, that's highly obscure and not typical of a Twisted application.  
Nevertheless, I believe it satisfies your requirements.  You might want to take 
a look at http://twistedmatrix.com/projects/core/documentation/howto/index.html 
for a gentler introduction, though.  In particular, the client and server 
HOWTOs.

I'll comment on your code below.

>
>Here's my code:
>
>############ SERVER ##########
>import socket
>import select
>
>mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>mySocket.bind(('', 11111))
>mySocket.listen(1)
>
>clientlist = []
>
>while True:
>   connection, details = mySocket.accept()
>   print 'We have opened a connection with', details
>   clientlist.append(connection)
>   readable = select.select(clientlist, [], [])
>   msg = ''
>   for i in readable[0]:

You'll need to monitor sockets for disconnection.  The way you do this varies 
between platforms.  On POSIX, a socket will become readable but reading from it 
will return ''.  On Win32, a socket will show up in the exceptions set (which 
you are not populating).  With the below loop, your server will go into an 
infinite loop whenever a client disconnects, because the chunk will be empty 
and the message will never get long enough to break the loop.

>      while len(msg) < 1024:
>         chunk = i.recv(1024 - len(msg))
>         msg = msg + chunk

Additionally, select() has only told you that at least /one/ recv() call will 
return without blocking.  Since you call recv() repeatedly, each time through 
the loop after the first has the potential to block indefinitely, only 
returning when more bytes manage to arrive from the client.  This is most 
likely the cause of the freezes you are seeing.  Instead, call recv() only once 
and buffer up to 1024 (if this is really necessary - I do not think it is) over 
multiple iterations through the outermost loop (the "while True:" loop).

>
>   for i in clientlist:
>      totalsent = 0
>      while totalsent < 1024:
>         sent = i.send(msg)
>         totalsent = totalsent + sent

This isn't quite right either - though it's close.  You correctly monitor how 
much of the message you have sent to the client, since send() may not send the 
entire thing.  However there are two problems.  One is trivial, and probably 
just a think-o: each time through the loop, you re-send `msg', when you 
probably meant to send `msg[totalsent:]' to avoid duplicating the beginning of 
the message and losing the end of it.  The other problem is that the send() 
call may block.  You need to monitor each socket for write-readiness (the 2nd 
group of sockets to select()) and only call send() once for each time a socket 
appears as writable.

>
>############## CLIENT ################
>import socket
>import select
>
>socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>socket.connect(("127.0.0.1", 11111))
>
>while True:
>    text = raw_input("Du bist an der Reihe")
>    text = text + ((1024 - len(text)) * ".")
>    totalsent = 0
>    while totalsent < len(text):
>        sent = socket.send(text)
>        totalsent = totalsent + sent

Similar problem here as in the server-side send() loop - 
`send(text[totalsent:])' instead of sending just `text'.

>
>    msg = ''
>    while len(msg) < 1024:
>        chunk = socket.recv(1024 - len(msg))
>        msg = msg + chunk

This is problematic too, since it means you will only be able to send one 
message for each message received from the server, and vice versa.  Most chat 
sessions don't play out like this.

>
>    print msg

I encourage you to take a look at Twisted.  It takes care of all these little 
details in a cross-platform manner, allowing you to focus on your unique 
application logic, rather than solving the same boring problems that so many 
programmers before you have solved.

Hope this helps,

Jp
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to