Home > OS >  how to do something like streams inside a port (Python socket)
how to do something like streams inside a port (Python socket)

Time:09-07

there is such a code:

server:

import socket
from threading import Thread
from time import sleep

sock = socket.socket()

sock.bind(('', 1337))
sock.listen(1)
conn, addr = sock.accept()
def func1():
    while True:
        conn.send("1".encode("utf-8"))
        sleep(0.5)
def func2():
    while True:
        conn.send("2".encode("utf-8"))
        sleep(0.5)
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()

client:

import socket
from threading import Thread
from time import sleep

sock = socket.socket()
sock.connect(('localhost', 1337))

def func1():
    while True:
        data = sock.recv(1024).decode("utf-8")
        if data != "1":
            print("the package did not arrive properly")
        else:
            print("package arrived ok")
def func2():
    while True:
        data = sock.recv(1024).decode("utf-8")
        if data != "2":
            print("the package did not arrive properly")
        else:
            print("package arrived ok")
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()

I need to make sure that the packet sent by function1 comes to function1, and the packet of function2 comes to function2, but this code does not work correctly, and packets from function1 often end up in function2 and vice versa

CodePudding user response:

I feel like you are approaching this from the wrong direction. You do not need multiple threads in the server or client. If you have multiple threads that is fine, but that's really not relevant for the problem you are having.

You are trying to multiplex multiple different types of messages over a single socket connections. In other words, you need a communication protocol.

On top of that, you have another problem that you do not appear to be aware of yet. Sockets are streams of bytes, in particular, they are not messages. If you send multiple messages in quick succession, they might be truncated or combined in the receiver.

If you send the following packages:

1
2
1
1
2

They could be received as follows:

12
112

Then your receiver will be very confused. Again, this problem can be resolved with a communication protocol.


There are many different ways to implement a communication protocol. The simplest that I can think of is to use JSON:

# sender.py

import socket
import time
import json

sock = socket.socket()

# https://stackoverflow.com/a/6380198/8746648
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

sock.bind(('', 1337))
sock.listen(1)
conn, addr = sock.accept()

while True:
    # If necessary, you can make these calls from different threads.
    # Notice, that we append a newline at the end, this is needed for 'readline' to work properly.
    conn.send(json.dumps({ "type": 1, "payload": 42 }).encode("utf-8")   b"\n")
    time.sleep(0.5)
    conn.send(json.dumps({ "type": 2, "payload": "can-be-anything" }).encode("utf-8")   b"\n")
    time.sleep(0.5)
# receiver.py

import socket
import json

sock = socket.socket()
sock.connect(('localhost', 1337))

# We know, that the messages themselves do not contain newline characters
# and the server sends a newline after each message, therefore, this will receive a complete message.
sock_file = sock.makefile()
while line := sock_file.readline():
    object_ = json.loads(line)

    # If you want to you can handle the messages in different threads.
    # This could be done by setting up a queue that is consumed by working threads.
    if object_["type"] == 1:
        print(f"received(1): {object}")
    elif object_["type"] == 2:
        print(f"received(2): {object}")

CodePudding user response:

If you are willing you could use multiple ports

<Client>

import socket
from threading import Thread
from time import sleep


def func1():
    sock = socket.socket()
    sock.connect(('localhost', 1338))
    while True:

        data = sock.recv(1024).decode("utf-8")
        if data != "1":
            print("the package did not arrive properly")
        else:
            print("package arrived ok")
def func2():
    sock = socket.socket()
    sock.connect(('localhost', 1337))
    while True:

        data = sock.recv(1024).decode("utf-8")
        if data != "2":
            print("the package did not arrive properly")
        else:
            print("package arrived ok")
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()

<Server>

import socket
from threading import Thread
from time import sleep

def func1():
    sock = socket.socket()
    sock.bind(('', 1338))
    sock.listen(1)
    conn, addr = sock.accept()
    while True:
        conn.send("1".encode("utf-8"))
        sleep(0.5)
def func2():
    sock = socket.socket()
    sock.bind(('', 1337))
    sock.listen(1)
    conn, addr = sock.accept()
    while True:
        conn.send("2".encode("utf-8"))
        sleep(0.5)
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()

  • Related