1

I am working for the first time on sockets with python. I need to connect more than a client socket to the same server socket.

To do this I used the the following code:

import socket
import time
import random

from threading import Thread
import thread
import subprocess, signal, os

class ServerObject:
    def __init__(self, port):
        self.socket = ''
        self.host = ''
        self.port = port
        self.conn = ''
        self.data = ''

        print "Server port is: ", self.port

        def openSocketConnectionAsServer(self):
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.bind((self.host, self.port))
            self.socket.listen(5)
            self.conn, addr = self.socket.accept()
            print 'Server Connected by', addr

        def getData(self):
            return self.data

        def getHost(self):
            return self.host

        def getPort(self):
            return self.port

        def sendMessage(self, message):
            try :
                self.conn.sendall(message)
            except socket.error:
                print 'Server Send failed'
                sys.exit()

        def receiveMessageFromClient(self):
            while 1:
                reply = self.conn.recv(4096)
                if not self.data: break
                return reply

        def receiveMessageFromServer(self):
            reply = self.socket.recv(4096)
            return reply

        def closeConnectionAsServer(self):
            self.socket.shutdown(1)
            self.socket.close()
            del self.socket

class ClientObject:    
    def __init__(self):
        self.data = str(random.choice('abcdefghil'))
        print "Client Data Random: ", self.data
        self.host = 'localhost'
        self.port = ''

    def openSocketConnectionAsClient(self):
        self.port = 50000 + random.randint(1,3)
        print "Client socket port is: ", self.port
        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        except socket.error:
            print 'Client Failed to create socket'
            sys.exit()

        print 'Client Socket Created'

        try:
            remote_ip = socket.gethostbyname( self.host )
        except socket.gaierror:
            print 'Client Hostname could not be resolved. Exiting'
            sys.exit()

        self.socket.connect((remote_ip , self.port))

    def getData(self):
        return self.data

    def getHost(self):
        return self.host

    def getPort(self):
        return self.port

    def sendMessage(self, message):
        try :
            self.socket.sendall(message)
        except socket.error:
            print 'Client Send failed'
            os.sys.exit()

    def receiveMessageFromServer(self):
        reply = self.socket.recv(4096)
        return reply

    def closeConnection(self):
        self.socket.shutdown(1)
        self.socket.close()
        del self.socket

def clientProcess():
    print "Client Start the client process"
    client1 = ClientObject()
    for i in range(1,10): 
        try:
            print "Client try to open the connection socket: attempt number ",i
            client1.openSocketConnectionAsClient()
            print "Client connection socket established on port ", client1.getPort()
            break
        except socket.error:
            print "Client connection error on the port ", client1.getPort()
            if i == 10:
            os.sys.exit()

    print "Client send the message"
    client1.sendMessage(client1.getData())
    print "Client receive the message back"
    client1.receiveMessageFromServer()
    print "Client Data requested: ", client1.getData(), " Hostname: ", client1.getHost(), " Port: ", client1.getPort()
    print "Client Close connection"
    client1.closeConnection()

def serverProcess(port=40007):
    print "Server oject create"
    server = ServerObject(port)
    print "Server open connection as server"
    server.openSocketConnectionAsServer()
    print "Server receive the client message"
    receivedMessage = server.receiveMessageFromClient()
    message = "Server Data requested are: "+receivedMessage
    print "Server send the message back to the client"
    server.sendMessage(message)
    print "Server close the connection with the client"
    server.closeConnectionAsServer()


if __name__ == '__main__':

    threadServer = Thread(target=serverProcess, args=[50001])
    print "New Server thread created with name: ", threadServer.getName()
    threadServer.start()

    for i in range(1,3):
        threadClient = Thread(target=clientProcess)
        print "New Client thread created with name: ", threadClient.getName()
        threadClient.start()
        threadClient.join()

When I run it, the first client is able to connect to the server, the second one never get connected, even though I close the connection (from server and client side) at the end of the first client thread.

Please, could anybody tell me, what's wrong in my code?

Thanks

user2010771
  • 11
  • 1
  • 2
  • 1
    You need to create a new process or thread for each new client. This can by done inside the Python code, or outside using xinetd or similar tools. – Ber Jan 25 '13 at 14:29

2 Answers2

0

What @Ber said was correct but incomplete.

You're problem is here:

self.socket.listen(5)
self.conn, addr = self.socket.accept()

listen will open up the port and prepare to receive connections. accept will wait for the next connection.

While you only need to call listen once, you must call accept multiple times, once per connection. There are several ways you can arrange this. For starters you could call accept again when the current connection closes, but this will only allow one client at a time. Better to have one thread call accept to wait for the next connection, but have it start a worker thread to handle each one.

Or you could use non-blocking I/O, but if you go this way, check out Twisted.

Community
  • 1
  • 1
jimhark
  • 4,938
  • 2
  • 27
  • 28
  • More importantly - `accept` blocks until a client connects and then returns the ephemeral socket that is used to read+write to the client. – D.Shawley Jan 25 '13 at 14:41
0

I would highly recommend using the excellent socketserver module for doing stuff like this. As for your code, the problem is that your threaded socket server only runs in a single thread. At the very least, you should create a new thread to handle the connection after accepting the new connection in openSocketConnectionAsServer.

D.Shawley
  • 58,213
  • 10
  • 98
  • 113