Home > Back-end >  how to use threading in sockets in python?
how to use threading in sockets in python?

Time:06-10

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)
  • Related