I have a following code that handle with sockets in Python:
import socket
HOST = "127.0.0.1"
PORT = 4999
TIMEOUT = 1
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT)) #
s.listen()
conn, addr = s.accept()
conn.settimeout(TIMEOUT)
with conn:
print(f"Connected by {addr}")
while True:
recieved = conn.recv(1024)
print(recieved)
I open a terminal and run this python script using python3 server.py
. It works, but when the first connection is closed, my script ends. I would like to be able to handle with multiple connections. In other words, when the first connection closes, I would like to wait for the second, third connection etc.
I try to do this with threading
. See below:
import socket
import threading
HOST = "127.0.0.1"
PORT = 4999
TIMEOUT = 1
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT)) #
s.listen()
conn, addr = s.accept()
conn.settimeout(TIMEOUT)
threading.Lock()
with conn:
print(f"Connected by {addr}")
while True:
recieved = conn.recv(1024)
print(recieved)
but the situation is the same. What do I do wrong, please?
CodePudding user response:
Something like this:
Main thread receives data and append to list. Thread monitors list for data to do whatever.
def receive_tcp_packets(self):
server_socket.bind(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
server_socket.listen()
server_conn, address = server_socket.accept()
# Wait for connection
with server_conn:
print("Connected by {}".format(str(address)))
# Wait to receive data
while True:
data = server_conn.recv(self.packet_size)
# Just keep appending the data
self.recv_data.append(data)
if not data:
break
# Close connection
server_socket.close()
def run_server(self):
while True:
self.receive_tcp_packets()
# Run the function that process incoming data
thread = threading.Thread(target=check_for_data, args = (xxx))
thread.start
# Run the main function that waits for incoming data
server_socket.run_server()
CodePudding user response:
You don't need threads to handle serial connections, and your example "with threads" didn't use threads at all. It just created (and didn't save) a threading.Lock
object. Use a while
loop to accept the next connection:
import socket
HOST = ''
PORT = 4999
with socket.socket() as s:
s.bind((HOST, PORT))
s.listen()
while True:
conn, addr = s.accept()
with conn:
print(f"Connected by {addr}")
while True:
received = conn.recv(1024)
if not received: break # connection was closed
print(received)
print(f"Disconnected by {addr}")
Manual 2-client demo:
>>> from socket import *
>>> s=socket()
>>> s.connect(('localhost',4999))
>>> s.sendall(b'hello')
>>> s.close()
>>> s=socket()
>>> s.connect(('localhost',4999))
>>> s.sendall(b'goodbye')
>>> s.close()
Server output:
Connected by ('127.0.0.1', 19639)
b'hello'
Disconnected by ('127.0.0.1', 19639)
Connected by ('127.0.0.1', 19640)
b'goodbye'
Disconnected by ('127.0.0.1', 19640)
If you need parallel connections, start a thread for each connection:
import socket
import threading
HOST = '' # typically listen on any interface on the server. "127.0.0.1" will only accept connections on the *same* computer.
PORT = 4999
def handler(conn,addr):
with conn:
print(f"Connected by {addr}")
while True:
received = conn.recv(1024)
if not received: break # connection was closed
print(f'{addr}: {received}')
print(f"Disconnected by {addr}")
with socket.socket() as s:
s.bind((HOST, PORT))
s.listen()
while True:
conn, addr = s.accept()
threading.Thread(target=handler, args=(conn,addr)).start()
Manual demo of 2 clients connecting at the same time:
>>> from socket import *
>>> s=socket()
>>> s.connect(('localhost',4999))
>>> s2=socket()
>>> s2.connect(('localhost',4999))
>>> s.sendall(b'hello')
>>> s2.sendall(b'goodbye')
>>> s.close()
>>> s2.close()
Server output:
Connected by ('127.0.0.1', 19650)
Connected by ('127.0.0.1', 19651)
('127.0.0.1', 19650): b'hello'
('127.0.0.1', 19651): b'goodbye'
Disconnected by ('127.0.0.1', 19650)
Disconnected by ('127.0.0.1', 19651)