Python Socket Multiple Clients
Solution 1
Based on your question:
My question is, using the code below, how would you be able to have multiple clients connected? I've tried lists, but I just can't figure out the format for that. How can this be accomplished where multiple clients are connected at once and I am able to send a message to a specific client?
Using the code you gave, you can do this:
#!/usr/bin/python # This is server.py file
import socket # Import socket module
import thread
def on_new_client(clientsocket,addr):
while True:
msg = clientsocket.recv(1024)
#do some checks and if msg == someWeirdSignal: break:
print addr, ' >> ', msg
msg = raw_input('SERVER >> ')
#Maybe some code to compute the last digit of PI, play game or anything else can go here and when you are done.
clientsocket.send(msg)
clientsocket.close()
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 50000 # Reserve a port for your service.
print 'Server started!'
print 'Waiting for clients...'
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
print 'Got connection from', addr
while True:
c, addr = s.accept() # Establish connection with client.
thread.start_new_thread(on_new_client,(c,addr))
#Note it's (addr,) not (addr) because second parameter is a tuple
#Edit: (c,addr)
#that's how you pass arguments to functions when creating new threads using thread module.
s.close()
As Eli Bendersky mentioned, you can use processes instead of threads, you can also check python threading
module or other async sockets framework. Note: checks are left for you to implement how you want and this is just a basic framework.
Solution 2
accept
can continuously provide new client connections. However, note that it, and other socket calls are usually blocking. Therefore you have a few options at this point:
- Open new threads to handle clients, while the main thread goes back to accepting new clients
- As above but with processes, instead of threads
- Use asynchronous socket frameworks like Twisted, or a plethora of others
Solution 3
Here is the example from the SocketServer documentation which would make an excellent starting point
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
"""
The RequestHandler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print "{} wrote:".format(self.client_address[0])
print self.data
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
Try it from a terminal like this
$ telnet localhost 9999
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello
HELLOConnection closed by foreign host.
$ telnet localhost 9999
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Sausage
SAUSAGEConnection closed by foreign host.
You'll probably need to use A Forking or Threading Mixin too
Solution 4
This program will open 26 sockets where you would be able to connect a lot of TCP clients to it.
#!usr/bin/python
from thread import *
import socket
import sys
def clientthread(conn):
buffer=""
while True:
data = conn.recv(8192)
buffer+=data
print buffer
#conn.sendall(reply)
conn.close()
def main():
try:
host = '192.168.1.3'
port = 6666
tot_socket = 26
list_sock = []
for i in range(tot_socket):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host, port+i))
s.listen(10)
list_sock.append(s)
print "[*] Server listening on %s %d" %(host, (port+i))
while 1:
for j in range(len(list_sock)):
conn, addr = list_sock[j].accept()
print '[*] Connected with ' + addr[0] + ':' + str(addr[1])
start_new_thread(clientthread ,(conn,))
s.close()
except KeyboardInterrupt as msg:
sys.exit(0)
if __name__ == "__main__":
main()
Alec
Updated on August 18, 2021Comments
-
Alec over 2 years
So I am working on an iPhone app that requires a socket to handle multiple clients for online gaming. I have tried Twisted, and with much effort, I have failed to get a bunch of info to be sent at once, which is why I am now going to attempt socket.
My question is, using the code below, how would you be able to have multiple clients connected? I've tried lists, but I just can't figure out the format for that. How can this be accomplished where multiple clients are connected at once and I am able to send a message to a specific client?
Thank you!
#!/usr/bin/python # This is server.py file import socket # Import socket module s = socket.socket() # Create a socket object host = socket.gethostname() # Get local machine name port = 50000 # Reserve a port for your service. print 'Server started!' print 'Waiting for clients...' s.bind((host, port)) # Bind to the port s.listen(5) # Now wait for client connection. c, addr = s.accept() # Establish connection with client. print 'Got connection from', addr while True: msg = c.recv(1024) print addr, ' >> ', msg msg = raw_input('SERVER >> ') c.send(msg); #c.close() # Close the connection
-
Mayli almost 12 yearsMake a while of
c, addr = s.accept()
when a client connected store them in a client_list, and then start a Thread of it. -
Alec almost 12 yearsWould it be like.... while: c, addr = s.accept() client_list = [] client_list.append(c, addr)
-
sarnold almost 12 yearsI know it's a huge change, but consider Ruby's EventMachine -- I found the EventMachine documentation significantly easier to read and understand than the Twisted documentation. The downside to Ruby is the smaller ecosystem of library bindings and packages, but it's better than it once was...
-
Alec almost 12 years@sarnold I would rather stick with Python, I just feel it would be good to stick with it. Thanks for your suggestion though.
-
Mayli almost 12 years@AlecK. You need to have the
client_list=[]
out of the while loop, a good example is here, if you want just C-c C-v. -
sarnold almost 12 years@AlecK., yeah, I can understand, especially if you've got other code written in Python. It just strikes me every time I see Twisted documentation how complicated they've made some things...
-
Alec almost 12 years@Mayli I am not very experienced in this, so I can't quite figure it out. I'm not understanding it good enough.
-
Mayli almost 12 years@AlecK. Did you check the example link? Modify that example then run it, and you will get what you want. The Server class could handle multiple clients. If you want to learn more, read the code.
-
Alec almost 12 years@Mayli So I can't just use lists? It has to be that in-depth? I know when I used Twisted it seemed simpler.
-
Mayli almost 12 years@AlecK. Twisted is a more complex twisted asynchronous lib than the example give. If you are making a really complex project, it's worth spending time learning it. When you using lists, it more like a synchronous way in which your code is blocked in every network communication.
-
Alec almost 12 years@Mayli Can you give me a start in this while loop? I just can't think right now. :(
-
Daniel F over 5 yearsA thread per client does not scale. I know Twisted is hard to get into, but once you have some experience with it, it is the goto-tool for almost all network related stuff. Stuff like the one you're trying to solve.
-
-
hoangpx over 7 yearsCould you check this again. I got this error " data = clientsocket.recv(16384) AttributeError: 'tuple' object has no attribute 'recv'"
-
cascading-style almost 7 yearsIs there a way to keep multiple connections alive using this?
-
ViFI almost 6 yearsTowards the 3rd point, Python now (3.5 onwards) has an in-built support of "asyncio" for asynchronous programming
-
nog642 almost 5 yearsThe
clientsocket.close()
after thewhile True:
in the function and thes.close()
after thewhile True:
at the bottom will never be called, since there are nobreak
s in thewhile True:
and the only way to exit the loop is with an exception, that will not be caught and will end the thread. A context manager would be a better way to make sure the socket is closed. -
NaNdy about 4 yearsI have adapted your program for python3 and it is coming up with this error Traceback (most recent call last): File "mydir\Server.py", line 29, in <module> print(f"Got connection from \"{addr}\"") NameError: name 'addr' is not defined
-
Vladimir Stazhilov almost 4 years@cascading-style I don't think so, I tried that because I had multiple client connections, and it was randomely timing out
-
Jonathan over 3 yearsShouldn't
import thread
readfrom threading import Thread
andthread.start_new_thread()
then be replaced byThread(target=on_new_client, args=(c,addr))
at least for Python 3? -
Abdul Aziz Barkat about 3 yearsWhile this may answer the question, please consider adding an explanation.
-
Patrizio Bertoni over 2 yearsYes there's a simple way, just instantiate a
socketserver.ThreadingTCPServer
instead of asocketserver.TCPServer
(at least on a modern python interpreter such as 3.8.8)