54

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
Basj
47.6k113 gold badges467 silver badges819 bronze badges
asked May 30, 2012 at 5:01
12
  • 4
    Make a while of c, addr = s.accept() when a client connected store them in a client_list, and then start a Thread of it. Commented May 30, 2012 at 5:12
  • 2
    Would it be like.... while: c, addr = s.accept() client_list = [] client_list.append(c, addr) Commented May 30, 2012 at 5:16
  • 1
    I 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... Commented May 30, 2012 at 5:18
  • @sarnold I would rather stick with Python, I just feel it would be good to stick with it. Thanks for your suggestion though. Commented May 30, 2012 at 5:19
  • 2
    @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... Commented May 30, 2012 at 5:21

9 Answers 9

58

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.

rkta
4,6898 gold badges31 silver badges39 bronze badges
answered Oct 31, 2016 at 21:40
Sign up to request clarification or add additional context in comments.

5 Comments

Could you check this again. I got this error " data = clientsocket.recv(16384) AttributeError: 'tuple' object has no attribute 'recv'"
The clientsocket.close() after the while True: in the function and the s.close() after the while True: at the bottom will never be called, since there are no breaks in the while 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.
I 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
Shouldn't import thread read from threading import Thread and thread.start_new_thread() then be replaced by Thread(target=on_new_client, args=(c,addr)) at least for Python 3?
this answer is VERY old. stackoverflow.com/questions/6319268/…
25

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
answered May 30, 2012 at 6:04

1 Comment

Towards the 3rd point, Python now (3.5 onwards) has an in-built support of "asyncio" for asynchronous programming
8

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

answered May 30, 2012 at 6:05

3 Comments

Is there a way to keep multiple connections alive using this?
@cascading-style I don't think so, I tried that because I had multiple client connections, and it was randomely timing out
Yes there's a simple way, just instantiate a socketserver.ThreadingTCPServer instead of a socketserver.TCPServer (at least on a modern python interpreter such as 3.8.8)
4

This is what I've done in python 3.

import socket
from threading import Thread
def on_new_client(client_socket, addr):
 while True:
 data = client_socket.recv(1024).decode('utf-8')
 if not data:
 break
 print(f"{addr} >> {data}")
 client_socket.close()
def main():
 host = '0.0.0.0' # allow any incoming connections
 port = 8888
 s = socket.socket()
 s.bind((host, port)) # bind the socket to the port and ip address
 s.listen(5) # wait for new connections
 while True:
 c, addr = s.accept() # Establish connection with client.
 # this returns a new socket object and the IP address of the client
 print(f"New connection from: {addr}")
 thread = Thread(target=on_new_client, args=(c, addr)) # create the thread
 thread.start() # start the thread
 c.close()
 thread.join()
if __name__ == '__main__':
 main()

https://docs.python.org/3/library/threading.html#introduction https://docs.python.org/3/library/socket.html#example

Kęstutis
1191 silver badge8 bronze badges
answered May 4, 2023 at 19:03

Comments

2

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()
RaminNietzsche
2,8111 gold badge24 silver badges37 bronze badges
answered Apr 20, 2017 at 17:28

Comments

0
def get_clients():
 first_run = True
 startMainMenu = False
 while True:
 if first_run:
 global done
 done = False
 Thread(target=animate, args=("Waiting For Connection",)).start()
 Client, address = objSocket.accept()
 global menuIsOn
 if menuIsOn:
 menuIsOn = False # will stop main menu
 startMainMenu = True
 done = True
 # Get Current Directory in Client Machine
 current_client_directory = Client.recv(1024).decode("utf-8", errors="ignore")
 # beep on connection
 beep()
 print(f"{bcolors.OKBLUE}\n***** Incoming Connection *****{bcolors.OKGREEN}")
 print('* Connected to: ' + address[0] + ':' + str(address[1]))
 try:
 get_client_info(Client, first_run)
 except Exception as e:
 print("Error data received is not a json!")
 print(e)
 now = datetime.now()
 current_time = now.strftime("%D %H:%M:%S")
 print("* Current Time =", current_time)
 print("* Current Folder in Client: " + current_client_directory + bcolors.WARNING)
 connections.append(Client)
 addresses.append(address)
 if first_run:
 Thread(target=threaded_main_menu, daemon=True).start()
 first_run = False
 else:
 print(f"{bcolors.OKBLUE}* Hit Enter To Continue.{bcolors.WARNING}\n#>", end="")
 if startMainMenu == True:
 Thread(target=threaded_main_menu, daemon=True).start()
 startMainMenu = False
answered Jan 30, 2021 at 14:20

1 Comment

While this may answer the question, please consider adding an explanation.
0

I tried a lot to deal with TCPServer and multiple connections.

The most stable and easy way is to use ThreadingTCPServer

Thanks to the comment of PatrizioBertoni!

socks = socketserver.ThreadingTCPServer(("0.0.0.0", port), SockHandler)
answered May 26, 2023 at 8:04

Comments

0

Here is a simple server, it uses threading.Thread to handle multiple clients concurrently:

import socket, threading
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('', 555))
serversocket.listen(5)
def client_listener(connection, address):
 print(f"New connection {connection=} {address=}")
 while True:
 buf = connection.recv(64)
 if not buf:
 print(f"Closing connection {connection=} {address=}")
 break
 print(buf)
while True:
 connection, address = serversocket.accept()
 threading.Thread(target=client_listener, args=(connection, address)).start()

and a client:

import socket, time
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('localhost', 555))
clientsocket.send(b'hello1')
time.sleep(5)
clientsocket.send(b'hello2')
answered Oct 8, 2023 at 8:57

Comments

-2
#!/usr/bin/python
import sys
import os
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
port = 50000
try:
 s.bind((socket.gethostname() , port))
except socket.error as msg:
 print(str(msg))
s.listen(10)
conn, addr = s.accept() 
print 'Got connection from'+addr[0]+':'+str(addr[1]))
while 1:
 msg = s.recv(1024)
 print +addr[0]+, ' >> ', msg
 msg = raw_input('SERVER >>'),host
 s.send(msg)
s.close()
answered Oct 27, 2017 at 16:56

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.