Reputation: 3264
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
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
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