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

Problem with socket programing

VPS Starter Arubacloud
0 głosów
181 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 (349,420 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 262 wizyt
0 głosów
1 odpowiedź 315 wizyt
pytanie zadane 28 października 2020 w Python przez WojtaZio23 Użytkownik (660 p.)
0 głosów
0 odpowiedzi 223 wizyt
pytanie zadane 27 października 2020 w Python przez WojtaZio23 Użytkownik (660 p.)

93,008 zapytań

141,975 odpowiedzi

321,256 komentarzy

62,350 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

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...