Russ Adams
Russ Adams

Reputation: 73

Using Processes as Threads with Networking in Python

Basically, my idea was to write some sort of basic server where I could connect to my computer and then run a command remotely. This didn't seem to be much of a problem; but then I had the bright idea that the next step would logically be to add some sort of threading so I could spawn multiple connections.

I read that, because of the GIL, multiprocessing.Process would be the best to try to do this. I don't completely understand threading and it's hard to find good documentation on it; so I'm kind of just throwing stuff and trying to figure out how it works.

Well, it seems like I might be close to doing this right; but I have a feeling I'm just as likely to be no where near doing this correctly. My program now does allow multiple connections, which it didn't when I first started working with threading; but once a connection is established, and then another is established, the first connection is no longer able to send a command to the server. I would appreciate it if someone could give me any help, or point me in the right direction on what I need to learn and understand.

Here's my code:

class server:
    def __init__(self):
        self.s = socket.socket()
        try:
            self.s.bind(("",69696))
            self.s.listen(1)
        except socket.error,(value,message):
            if self.s:
                self.s.close()
    def connection(self):
        while True:
            client , address = self.s.accept()

            data = client.recv(5)
            password = 'hello'
            while 1:
                if data == password:
                    subprocess.call('firefox')
                    client.close()
                else:
                    client.send('wrong password')
                    data = client.recv(5)
            p = Process(target=x.connection())
            p.start()
x = server()

if __name__ == '__main':
    main()

Upvotes: 3

Views: 180

Answers (1)

entropy
entropy

Reputation: 3144

Well, this answer only applies if you're on a unix or unix-like operating system(windows does not have os.fork() which we use).

One of the most common approaches for doing these things on unix platforms is to fork a new process to handle the client connection while the master process continues to listen for requests.

Below is code for a simple echo server that can handle multiple simultaneous connections. You just need to modify handle_client_connection() to fit your needs

import socket
import os

class ForkingServer:
    def serve_forever(self):
        self.s = socket.socket()
        try:
            self.s.bind(("", 9000))
            self.s.listen(1)
        except socket.error, (value,message):
            print "error:", message
            if self.s:
                self.s.close()
            return

        while True:
            client,address = self.s.accept()
            pid = os.fork()
            # You should read the documentation for how fork() works if you don't
            # know it already
            # The short version is that at this point in the code, there are 2 processes
            # completely identical to each other which are simulatenously executing
            # The only difference is that the parent process gets the pid of the child
            # returned from fork() and the child process gets a value of 0 returned
            if pid == 0:
                # only the newly spawned process will execute this
                self.handle_client_connection(client, address)
                break
            # In the meantime the parent process will continue on to here
            # thus it will go back to the beginning of the loop and accept a new connection

    def handle_client_connection(self, client,address):
        #simple echo server
        print "Got a connection from:", address
        while True:
            data = client.recv(5)
            if not data:
                # client closed the connection
                break
            client.send(data)
        print "Connection from", address, "closed"


server = ForkingServer()
server.serve_forever()

Upvotes: 1

Related Questions