2

I created a messenger using Python Socket, when I use two clients, for example, when one user leaves the chat, the second user can send 1-2 more messages and after that the server stops accepting messages from other users, that is there is a well-known error Broken pipe 32. I understand the terminology of the error, perhaps the error lies on my server in a While True loop (a loop that includes all the actions that users carry out among themselves), because there is a fabulous code in the form:

if not data:
    print(f'User {name1} leave')
    break

but I need it, because without it the server will fly away in a straight word, and if a similar mechanism is made, the server will still be able to receive information from users.

Hope for mutual understanding, any help would be accepted and appreciated. Server and client code is below:

server: 

import socket
import threading
import time

HOST = '127.0.0.1'
PORT = 8888

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))

server.listen(15)
print(f'Server {HOST}:{PORT} start.')

users = [] 
sort = []


def crypto(text, key):
    encrypt = ''

    for i in text:
        encrypt += chr(ord(i) + key)

    return encrypt   


def listen_decode(user, addr):
    print(f'User IP-address {addr[0]} login..')
    sort.append(user) 
    user.send('Encode'.encode('utf-8'))
    user.send('Name'.encode('utf-8'))
    name1 = user.recv(1024).decode('utf-8')
    users.append(name1)

    
    while True:
        data = user.recv(1024).decode('utf-8')
        b1 = time.ctime()
        atribute = ' | '
        data_crypto = crypto(data, 4)
        print(f'{name1} sent message: {data_crypto} ' + atribute + '' + b1 + ' ')

        for i in sort:
            if(i != server and i != user):
                i.sendall(f'{name1} > {data}'.encode('utf-8'))
    
        if not data:
            print(f'User {name1} leave')
            break


def start_server():
    
    while True:
       user_socket, addr = server.accept()
       potok_info = threading.Thread(target=listen_decode, args=(user_socket, addr))
       potok_info.start()


if __name__ == '__main__':
    start_server()

client:

from tkinter import messagebox
from tkinter import *
import _tkinter 
import socket
import threading
import os


window = Tk()

window.title('Login')
window.geometry('320x200')
window.resizable(True, True)

HOST = '127.0.0.1'
PORT = 8888

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((HOST, PORT))

name = StringVar()
password = StringVar()

def encrypt(text, key):
    encrypt1 = ''

    for i in text:
        encrypt1 += chr(ord(i) - key)

    return encrypt1

def send_message():

    while True:
        data = client.recv(1024)
        print('\r\r' + data.decode('utf-8') + '\n' + f'you: ', end='')


def chat():

    string_name = name.get()

    if('Name' in client.recv(1024).decode('utf-8')):
        name1 = string_name
        client.send(name1.encode('utf-8'))

        potok = threading.Thread(target=send_message)
        potok.start()


        while True:
            msg = input('you: ')
            client.send(msg.encode('utf-8'))



def crypt():     
    
    string_name = name.get()
    string_password = password.get()

    try:
        user_encryption_selection = (encryption_listbox.get(encryption_listbox.curselection()))
    except _tkinter.TclError:
        messagebox.showerror('Error', 'Enter type message')



    if string_name == 'John':
        if string_password == '5555':
            if user_encryption_selection == 'Use Encrypted':
                window.after(1000, lambda: window.destroy())

                menu = Tk()

                menu.title('Menu Chat')
                menu.geometry('500x350')
                menu.resizable(False, False)

                menu_button = Button(menu, text='Global chat', command=chat, height=1, width=18)
                menu_button.grid(padx=150)

                menu.mainloop()
        else:
            messagebox.showerror('Error', 'Error password')
    else:
        messagebox.showerror('Error', 'Error name')

    
entry = Entry(window, textvariable=name, width=10)
entry.grid(column=1, pady=7, padx=4)

label = Label(window, text='Enter name: ')
label.grid(row=0, padx=1)

entry1 = Entry(window, textvariable=password, width=10)
entry1.grid(column=1, pady=7, padx=2)

label1 = Label(window, text='Enter password: ')
label1.grid(row=1, padx=1)

listbox = Listbox(window, selectmode=SINGLE, width=12, height=2)
listbox.grid(column=1, row=2, pady=7, padx=2)



encryption_options = ['Use Encrypted']
encryption_listbox = Listbox(window, selectmode=SINGLE, width=10, height=1)
encryption_listbox.grid(column=1, row=2, pady=7, padx=2)
for i in encryption_options:
    encryption_listbox.insert(END, i)  

label_crypto = Label(window, text='Type message: ', bg='black', fg='red')
label_crypto.grid(row=2)

button = Button(window, text='Enter', command=crypt)
button.grid(pady=30)



window.mainloop()
Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
John West
  • 43
  • 4
  • Please reduce your code to the absolute minimum necessary to reproduce the problem - the tkinter GUI and the crypto transformations are likely not needed for this. Also please describe exactly how the problem can be reproduced with the code and where the error is actually happening (client or server?) – Steffen Ullrich Nov 12 '21 at 03:22
  • Steffen, the problem here is not the encryption or GUI, but the server on the While True loop. I need to receive a message that the user has left the chat, but if I set 'if not data: break', the server will stop receiving messages, and if this command is not, the server will simply start writing that 'John send message: ' – John West Nov 12 '21 at 07:08
  • *"the problem here is not the encryption or GUI"* - exactly. And because of these code parts are not needed to reproduce the problem. Please keep the code your provide minimal. See [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). – Steffen Ullrich Nov 12 '21 at 07:26
  • If you are ready to help, I will leave here the minimum client without GUI and the same server where there is an identical error. But the client is useless here, I dropped it so you can go in and check how to fix the error. – John West Nov 12 '21 at 07:26

1 Answers1

1

perhaps the error lies on my server in a While True loop (a loop that includes all the actions that users carry out among themselves), because there is a fabulous code in the form:

if not data:
    print(f'User {name1} leave')
    break

You already spotted the place of the error's cause. The error occurs because the server keeps trying to send to a disconnected client (in the loop immediately above that code). To stop the server trying this, you just have to remove the client from sort (the list of connected clients) at that place where you recognize the disconnection, i. e. insert sort.remove(user) before the break.

Armali
  • 18,255
  • 14
  • 57
  • 171
  • 2
    Friend, I am very grateful to you for your help and understanding. You have no idea how many different manipulations I have performed to solve this problem. Thank you very much, I noticed your answer as the best, because you not only helped to solve a small problem that I did not notice, but also helped me to enjoy life again and sleep at night) – John West Nov 13 '21 at 11:52