Okay, so I'm currently working my way through Beginning Python: From Novice to Professional, and I'm up to the networking stuff. I consider myself at least an intermediate Python programmer, but the network stuff is really confusing me. I'm trying to get the hang of it by writing a simple chat server, which I would then like to someday evolve into a full chat program with a GUI and such. Here is my code so far:

import socket
import select

class ChatServer(object):
    def __init__( self, port ):
        self.port = port
        self.host = socket.gethostname()

        self.serversocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
        self.serversocket.bind( (self.host, self.port) )
        self.serversocket.listen( 5 )

        
        self.chatters = [self.serversocket]
        print "Chat server started on port %s" % port

    def run( self ):
        while True:

            (sread, swrite, sexc) = select.select( self.chatters, [], [], 10 )

            #print "test ", sread

            for sock in sread:

                if sock == self.serversocket:
                    self.accept_connection()

                else:

                    val = self.serversocket.recv(500)
                    (host, port) = sock.getpeername()

                    if val == "":
                        val = "Client disconnected %s:%s\n" % (host, port)
                        self.broadcast( val, sock )
                        sock.close
                        self.chatters.remove( sock )

                    else:
                        val = "[%s:%s] %s" % (host, port, val)
                        self.broadcast( val, sock )

    def accept_connection( self ):
        pass

    def broadcast( self, val, omitted ):
        pass

As you can see I haven't written accept_connection or broadcast yet, but the idea should be pretty obvious. I think I'm misinterpreting how select works though, because my little "test" thing just keeps telling me that it timed out. It's hard to find documentation of these areas for Windows environments. The idea is that it should wait for activity in self.chatters (one of the sockets), and then deal with that action appropriately, by reading the message, or accepting or closing the connection. The sread list keeps appearing empty however, and I feel like I should get that working before I try to accept any connections. Is there anything obvious I'm missing? Thanks!

Have you tried making a client locally and getting it to connect? Maybe the reason select fails to return any sockets is because no one is trying to connect. (Therefore there are no sockets to call accept on.)

Maybe you should try making a client instead of a server. You can make an IRC client along similar lines.

P.S. Unrelated to your problem, but "(sread, swrite, sexc) = ..." works fine without parentheses.

Okay, well in order to try doing the connection I coded the last remaining methods, so here's the code for the server in its entirety.

import socket
import select

class ChatServer(object):
    def __init__( self, port ):
        self.port = port
        self.host = socket.gethostname()

        self.serversocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
        self.serversocket.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
        self.serversocket.bind( (self.host, self.port) )
        self.serversocket.listen( 5 )

        
        self.chatters = [self.serversocket]
        print "Chat server started on port %s" % port

    def run( self ):
        while True:

            sread, swrite, sexc = select.select( self.chatters, [], [], 5 )

            print "test", sread

            for sock in sread:

                if sock == self.serversocket:
                    self.accept_connection()

                else:

                    val = self.serversocket.recv(500)
                    (host, port) = sock.getpeername()

                    if val == "":
                        val = "Client disconnected %s:%s\n" % (host, port)
                        self.broadcast( val, sock )
                        sock.close
                        self.chatters.remove( sock )

                    else:
                        val = "[%s:%s] %s" % (host, port, val)
                        self.broadcast( val, sock )

    def accept_connection( self ):
        newsock, (newhost, newport) = self.serversocket.accept()
        self.chatters.append( newsock )
        newsock.send( "You are connected to the server!\n" )

        val = "Client connected %s:%s\n" % (newhost, newport)
        self.broadcast( val, newsock )

    def broadcast( self, val, omitted ):
        for sock in self.chatters:
            if sock != self.serversocket and sock != omitted:
                sock.send(val)
        print val

As for the client, I've just been using telnet for now, but it fails to connect. Interestingly though, the telnet attempt never times out or gives an error, it just keeps trying to connect while the select call on the server keeps timing out.

Hm, well I must have changed something right because now it works it just takes a little bit to connect. However, the only "event" that is handled properly is a client (currently only through telnet) connecting. Disconnecting or trying to send a message causes the program to crash. I know this is because of the else on line 30, if the event isn't someone connecting this line is executed:
val = self.serversocket.recv(1024)

and that's giving me this error:
error: [Errno 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied

I'm not sure I understand, is it telling me my server socket isn't connected?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.