Pujan
Pujan

Reputation: 3264

Sockets & Inter communication Among Threads

I am using Multithreaded TCP Server. Each socket is created as a separate thread for each client. I would like send data to all clients via send() method of socket. Problem I am facing here is, it sends data to current thread (from which it received) only.

I could not find good documentation for inter thread communication for Python.

Any solution to my problem so that I can send data to all clients.

Thanks.

    #!/usr/bin/env python

    """
    A server with multithreading to handle multiple clients.
    """

    import select
    import socket
    import sys
    import threading
    import logging
    import datetime

    class Server:
        def __init__(self):
            self.host = ''
            self.port = 25000
            self.backlog = 5
            self.size = 1024
            self.server = None

        def open_socket(self):
            try:
                self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.server.bind((self.host,self.port))
                self.server.listen(5)
                lc.append(self.server)
            except socket.error, (value,message):
                if self.server:
                    self.server.close()
                print "Could not open socket: " + message
                sys.exit(1)

        def run(self):
            self.open_socket()
            input = [self.server,sys.stdin]
            running = 1
            while running:
                inputready,outputready,exceptready = select.select(input,[],[])

                for s in inputready:
                    if s == self.server:
                        c = Client(self.server.accept())
                        c.start()
                        threads.append(c)

            # close all threads
            self.server.close()
            for c in threads:
                c.join()

    class Client(threading.Thread):
        def __init__(self,(client,address)):
            threading.Thread.__init__(self)
            self.client = client
            self.address = address
            self.size = 1024
            dc[address[0]]=client#address[1]
            logging.info('%s added successfully...',address[0])


        def run(self):
            running = 1
            print dc
            while running:
                data = str(self.client.recv(self.size))
                #print dc

                if data.strip() == '0x01':
                    sendtoAll()
                elif data.strip() == '0x02':
                    self.client.send("version"+data)
                elif data.strip() == '0x03':#return current time
                    print datetime.datetime.now()
                    self.client.send(str(datetime.datetime.now()))
                else:
                    self.client.send("empty")
                    #self.client.close()
                    #running = 0
def sendtoAll():
        for i, sock in dc.items():
            print "Address:Sockets = ", i,sock
            try:
                print "sending to %s by Thread "%i
                sock.send("data"+str(threading.current_thread().getName()))
            except socket.error,e:
                print "error socket %s\n" % e
                sock.close()
                del lc[i]

if __name__ == "__main__":
        dc={}       #dict to store ip-address:scokets pair
        lc=[]       #tuples to store all sockets
        threads=[]  #holds threads
        logging.basicConfig(level=logging.INFO)
        logging.info('Starting Server Object...')
        s = Server()
        s.run()

And Client Code is

import socket
import sys

host = '192.168.1.4'
port = 25000
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
sys.stdout.write('%')

while 1:
    # read from keyboard
    line = sys.stdin.readline()
    if line == '\n':
        break
    s.send(line)
    data = s.recv(size)
    sys.stdout.write(data)
    sys.stdout.write('\n%')
s.close()

Upvotes: 1

Views: 2329

Answers (2)

Vatine
Vatine

Reputation: 21288

A TCP socket is one of two endpoints. There is no such thing as "broadcast" in TCP. If you want to send a single message to all your clients, you will have to send it to every one of them individually.

If you use a suitable container for all your client objects, it shoudl "just" be a matter of iterating across this, sending your message to each one.

Upvotes: 0

maaudet
maaudet

Reputation: 2358

You could make your threads objects (if any) iterable and you make a "broadcast" function that just iterate through your threads and use their sockets to send the information.

Or if you don't have an object per threads you can always just have a list of sockets and do pretty much the same thing.

Make sure that you use locks correctly based on your needs (Either for all the socket or each individual sockets)

Upvotes: 1

Related Questions