Reputation: 979
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
Upvotes: 54
Views: 232148
Reputation: 46353
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')
Upvotes: 0
Reputation: 1461
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)
Upvotes: 0
Reputation: 169
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()
Upvotes: 3
Reputation: 1
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
Upvotes: 0
Reputation: 963
#!/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()
Upvotes: -2
Reputation: 907
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.
Upvotes: 57
Reputation: 73
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()
Upvotes: 2
Reputation: 54117
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
Upvotes: 8
Reputation: 273806
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:
Upvotes: 24