• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Problem with socket programing

Object Storage Arubacloud
0 głosów
88 wizyt
pytanie zadane 6 sierpnia 2023 w Python przez Specjalny Nowicjusz (230 p.)

Hej ucze się pythona i chciałem zrobić projekt w którym potrzebuje nauczyć się troche socket programing. Napisałem prosty kod mający za zadanie wymiane wiadomości pomiędzy serverem i clientem. Mam problem z funkcją broadcast_message ponieważ wysłane w ten sposób wiadomości nie dochodzą do klienta. Co jest problemem?

 

#server.py
import socket
import threading
import time

HEADER = 64
FORMAT = "utf-8"
PORT = 5050
DISCONNECT_MESSAGE = "end!"
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)

clients = []
broadcast_queue = []  # List to hold messages for broadcasting

def handle_client(conn, addr):
    print(f"[NEW CONNECTION] {addr}")
    clients.append(conn)

    connected = True
    while connected:
        msg_length = conn.recv(HEADER).decode(FORMAT).strip()
        if msg_length:
            msg_length = int(msg_length)
            msg = conn.recv(msg_length).decode(FORMAT)
            if msg == DISCONNECT_MESSAGE:
                connected = False
            else:
                print(f"[{addr}] {msg}")
    
    conn.close()
    clients.remove(conn)
    print(f"[CONNECTION CLOSED] {addr}")

def broadcast_message(msg):
    message = msg.encode(FORMAT)
    msg_length = len(message)
    send_length = str(msg_length).encode(FORMAT)
    send_length += b' ' * (HEADER - len(send_length))
    
    for client_conn in clients:
        try:
            client_conn.send(send_length)
            client_conn.send(message)
        except:
            clients.remove(client_conn)

def broadcast_thread_func():
    while True:
        if broadcast_queue:
            msg = broadcast_queue.pop(0)  # Get the first message from the queue
            broadcast_message(msg)
        time.sleep(0.1)  # Adjust the sleep time as needed

def start_server():
    server.listen()
    print(f"Server is listening on {SERVER}")
    
    broadcast_thread = threading.Thread(target=broadcast_thread_func)  
    broadcast_thread.start()
    
    while True:
        conn, addr = server.accept()
        thread = threading.Thread(target=handle_client, args=(conn, addr))
        thread.start()
        clients.append(conn)
        print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 2}")  # Subtract the main thread and broadcast thread

start_thread = threading.Thread(target=start_server)
start_thread.start()

# # Call the broadcast_message function with needed parameter
# broadcast_queue.append("This is a broadcast message.")

# Create a separate thread for adding the message to the broadcast_queue
message_thread = threading.Thread(target=lambda: broadcast_queue.append("This is a broadcast message."))
message_thread.start()

 

#client.py
import socket
import threading

HEADER = 64
FORMAT = "utf-8"
PORT = 5050
DISCONNECT_MESSAGE = "end!"
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)

def send(msg):
    message = msg.encode(FORMAT)
    msg_length = len(message)
    send_length = str(msg_length).encode(FORMAT)
    send_length += b' ' * (HEADER - len(send_length))
    client.send(send_length)
    client.send(message)

def receive_messages():
    while True:
        msg_length = client.recv(HEADER).decode(FORMAT).strip()
        if msg_length:
            msg_length = int(msg_length)
            msg = client.recv(msg_length).decode(FORMAT)
            print(f"{msg}", end="")

send("hello")

receive_thread = threading.Thread(target=receive_messages)
receive_thread.start()

 

1 odpowiedź

+2 głosów
odpowiedź 6 sierpnia 2023 przez adrian17 Ekspert (344,860 p.)

Trzy główne obserwacje:

clients.append(conn)

To robisz przypadkiem dwukrotnie - raz z wątku accept(), raz z wątku połączenia.

message_thread = threading.Thread(target=lambda: broadcast_queue.append("This is a broadcast message."))

Nie rozumiem po co robisz to w wątku, ale - tak na oko, próbujesz zrobić broadcasta zanim jakikolwiek klient się połączył, więc nowi klienci nic nie dostaną.

print(f"{msg}", end="")

Wyrzuć ten end="" :)

A na boku:

SERVER = socket.gethostbyname(socket.gethostname())

Potrzebujesz takie kombinacje, czy nie wystarczy Ci obecnie zwykły ręcznie wpisany lookback 127.0.0.1?

{threading.active_count() - 2}

len(clients)? :D

I czemu wysyłasz długość wiadomości jako tekst (jeszcze w 64 bajtach), jak by się mogła spokojnie zmieścić w 8 bajtach (plus binarnie)?

komentarz 6 sierpnia 2023 przez Specjalny Nowicjusz (230 p.)
Dzięki bardzo, faktycznie próbowałem zrobić broadcast zanim jakikolwiek client się połączył i to było problemem

Podobne pytania

0 głosów
0 odpowiedzi 246 wizyt
0 głosów
1 odpowiedź 206 wizyt
pytanie zadane 28 października 2020 w Python przez WojtaZio23 Użytkownik (660 p.)
0 głosów
0 odpowiedzi 206 wizyt
pytanie zadane 27 października 2020 w Python przez WojtaZio23 Użytkownik (660 p.)

92,584 zapytań

141,433 odpowiedzi

319,668 komentarzy

61,966 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...