Trimiteți / primiți camera de chat Python nu funcționează (actualizat) (Programare, Python, Python 3.X, Prize, Tcp)

sistem123456 a intrebat.

Am pus o întrebare despre codul meu de la server la client pentru că am avut multe probleme cu și cineva mi-a spus că soluția la problemele pe care le aveam era să fac un chat peer to peer, ceea ce am făcut acum.

Server.py

import socket, threading

host = "127.0.0.1"
port = 4000
s = socket.socket()
s.bind((host,port))
s.listen(5)
client_sockets = []
users = []
print("Listening")

def handle_client(conn):
    while True:
        try:
            data = conn.recv(512)
            for x in client_sockets:
                try:
                    x.send(data)
                except Exception as e:
                    print(e)
        except:
            pass

while True:
    conn,addr = s.accept()
    client_sockets.append(conn)
    print("Connections from", addr[0], "on port",addr[1])
    threading.Thread(target = handle_client,args = (conn,)).start()

Client.py

import socket,threading

host = "127.0.0.1"
port = 4000
s = socket.socket()
s.connect((host,port))

def echo_data(sock):
   while True:
      try:
         data = sock.recv(512)
         print(data)
      except:
         pass

while True:
   threading.Thread(target=echo_data,args=(s,)).start()
   msg = input("Enter your message : ")
   s.send(msg.encode())

Problemele sunt că atunci când execut clientul și încerc să vorbesc cu un alt client, mesajul nu este trimis decât dacă celălalt client apasă enter și asta mă aduce și la a doua problemă, când clienții își trimit mesaje unul altuia, acestea sunt primite în acest format:

b'hi'Enter your message :

Acesta este linkul către întrebarea mea anterioară

Comentarii

  • @han solo Cum aș putea implementa select în codul meu? –  > Por sistem123456.
  • Verificați acest lucru. Acesta are tot ce ai nevoie. Și pierdeți filetarea. pymotw.com/2/select 🙂 –  > Por han solo.
  • @hansolo Am citit prin ea, dar încă nu sunt prea sigur cum să o implementez în codul meu, așa că ai putea să-mi arăți cum să te rog –  > Por sistem123456.
  • @hansolo Încearcă să folosească un fir pentru fiecare client. Cu acest design, blocarea firului unui client în așteptarea datelor de la acel client este în regulă. În mod similar, în clientul său, el are un singur fir al cărui scop este să blocheze așteptarea datelor de la server. Din nou, nu este nicio problemă să blochezi acest fir, deoarece singurul său scop este să aștepte date pe acea conexiune. –  > Por David Schwartz.
  • Nu cunosc python suficient de bine pentru a vă ajuta. Dar nu cred că este ceva foarte greșit în programul tău. Trebuie să schimbi intrarea din modul linie într-un mod mai brut și trebuie să convertești datele primite din octeți brute într-un șir de caractere imprimabil. În afară de asta, mi se pare în regulă. Serverul dvs. se va bloca dacă vreun client refuză să citească date de pe el, dar nu cred că vă pasă prea mult de rezistența la atacuri în acest moment. –  > Por David Schwartz.
1 răspunsuri
Serge Ballesta

Voi începe cu probleme generale care nu au legătură directă cu întrebarea:

  • except: pass este în general o idee proastă, mai ales atunci când lucrurile merg prost, deoarece va ascunde mesaje potențial utile. Este permisă de limbaj, dar nu ar trebui să existe niciodată în codul real
  • în client.py porniți un fir de recepție pentru fiecare mesaj, în timp ce aveți nevoie doar de unul pentru întregul client. Ar trebui să începeți firul în afara buclei:

    threading.Thread(target=echo_data,args=(s,)).start()
    while True:
       msg = input("Enter your message : ")
       s.send(msg.encode())
    

Acum, întrebările:

  • mesajul nu este trimis decât dacă celălalt client apasă enter.

    Poate fi cauzat de un IDE. Mai exact, se știe că IDLE se comportă prost cu scripturile cu mai multe fire. Dacă folosiți corect un singur fir de recepție și porniți scriptul din linia de comandă (python client.py), ar trebui să funcționeze corect

  • mesajele sunt recepționate în acest format: b'hi'Enter your message

    sock.recv(sz) returnează un șir de octeți. Trebuie să îl decodificați pentru a-l converti într-un șir Unicode Python 3:

     data = sock.recv(512)
     print(data.decode())
    

Dar asta nu este tot. Este în regulă pentru teste, dar ar trebui cel puțin să permiteți clienților să se deconecteze de la server și, atunci când o fac, să îi eliminați de la client_sockets. Și este obișnuit să nu se trimită înapoi un mesaj către expeditor. Deci, ați putea îmbunătăți bucla server.py:

while True:
    try:
        data = conn.recv(512)
        for x in client_sockets:
            if x != conn:         # do not echo to sender
                x.send(data)
    except Exception as e:        # problem in connection: exit the loop
        print(e)
        break
# clear the connection
conn.close()
client_sockets.remove(conn)

Comentarii

  • Am o altă problemă, când trimit un mesaj către un alt client, acesta este primit în acest format acum hiEnter your message : –  > Por sistem123456.
  • de asemenea, ce înseamnă print (e) face? –  > Por system123456.
  • @system123456: a fost o greșeală de scriere. Am uitat sfârșitul except specificației. –  > Por Serge Ballesta.
  • oh ok, aveți o soluție la problema mea? –  > Por sistem123456.
  • @system123456: Este ciudat că Enter your message : se repetă atunci când primim un mesaj. Ar trebui să se repete doar atunci când se trimite un mesaj. –  > Por Serge Ballesta.