0

I have a client-server socket python script. I want to keep the state of each connection, such that I identify whether or not the client is its first connection. I unsuccessfully wrote the following code:

import socket,sys,SocketServer
from threading import Thread


class EchoRequestHandler(SocketServer.BaseRequestHandler):

    def setup(self):
        self.clients = {}
        print self.client_address, 'connected!'
        self.request.send('hi ' + str(self.client_address) + '\n')


    def setup(self):
        print self.client_address, 'connected!'
        self.request.send('hi ' + str(self.client_address) + '\n')

def getFile(self):
        fle = self.request.makefile('r')
        filename = fle.readline()
        print("Got filename {}\n".format(filename))
        data = 'fnord' # just something to be there for the first comparison
        with open(filename[:-1], 'w') as outfile:
            while data:
                #data = self.request.recv(1024)
                data = fle.read()
                #print('writing {!r} to file ....'.format(data))
                outfile.write(data)
                print("Finish {}\n".format(filename))
        print("finish handle")
def handle(self):
    addr = self.client_address[0] 
    print(self.clients)
    if addr not in self.clients:
        print("firsttime")
        self.clients[addr]=1
        print(self.clients)
    self.getFile()

def finish(self):
    print self.client_address, 'disconnected!'
    #self.request.send('bye ' + str(self.client_address) + '\n')

class ThreadedTCPServer(SocketServer.ThreadingMixIn, 
SocketServer.TCPServer):
    pass
if __name__=='__main__':
        #server = SocketServer.ThreadingTCPServer(('localhost', 50000), EchoRequestHandler)
        server = ThreadedTCPServer(('localhost', 60000), EchoRequestHandler)
        server.serve_forever()

Each time the client connect I am getting an empty clients dictionary. Seems like each time there is a connection setup is being called and empties the dictionary clients. How can I keep its state at each connection?

Cœur
  • 37,241
  • 25
  • 195
  • 267
curious
  • 1,524
  • 6
  • 21
  • 45

1 Answers1

1

The threaded socket server creates a new instance of EchoRequestHandler for each connection, so storing the clients in that class instance would not be correct.

Each request handler instance has a self.server member that knows its server, so you can store it there instead.

Below is modified from a Python 2.7 SocketServer example in the module's help:

#!python2
import time
import socket
import threading
import SocketServer

class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        self.server.clients.add(self.client_address)
        print 'connected from',self.client_address
        print 'all clients =',self.server.clients
        data = self.request.recv(1024)
        cur_thread = threading.current_thread()
        response = "{}: {}".format(cur_thread.name, data)
        self.request.sendall(response)
        time.sleep(2)
        print 'disconnected'

class ThreadedTCPServer(SocketServer.ThreadingTCPServer):
    def __init__(self,*args,**kwargs):
        SocketServer.ThreadingTCPServer.__init__(self,*args,**kwargs)
        self.clients = set()

def client(ip, port, message):
    sock = socket.socket()
    sock.connect((ip, port))
    try:
        sock.sendall(message)
        response = sock.recv(1024)
        print "Received: {}".format(response)
    finally:
        sock.close()

if __name__ == "__main__":
    # Port 0 means to select an arbitrary unused port
    HOST, PORT = "localhost", 0

    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
    ip, port = server.server_address

    # Start a thread with the server -- that thread will then start one
    # more thread for each request
    server_thread = threading.Thread(target=server.serve_forever)
    # Exit the server thread when the main thread terminates
    server_thread.daemon = True
    server_thread.start()
    print "Server loop running in thread:", server_thread.name

    client(ip, port, "Hello World 1\n")
    client(ip, port, "Hello World 2\n")
    client(ip, port, "Hello World 3\n")

    server.shutdown()
    server.server_close()

Output:

Server loop running in thread: Thread-1
connected from ('127.0.0.1', 2360)
all clients = set([('127.0.0.1', 2360)])
Received: Thread-2: Hello World 1

connected from ('127.0.0.1', 2361)
all clients = set([('127.0.0.1', 2361), ('127.0.0.1', 2360)])
Received: Thread-3: Hello World 2

connected from ('127.0.0.1', 2362)
all clients = set([('127.0.0.1', 2361), ('127.0.0.1', 2362), ('127.0.0.1', 2360)])
Received: Thread-4: Hello World 3

disconnected
disconnected
disconnected
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • Thanks, that is what i need. One question. When you launch the server, it is needed to start it in a thread with `server_thread =threading.Thread(target=server.serve_forever)`?. It does not suffice the way i launch it: `server = ThreadedTCPServer(('localhost', 60000), EchoRequestHandler) server.serve_forever()`? – curious Aug 18 '16 at 03:58
  • 1
    @curious No, that was just so the clients and server could all run in one Python process. If you have separate Python scripts for the server and client it is not needed. – Mark Tolonen Aug 18 '16 at 16:15