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()
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
.