I created a messenger using Python Socket, when I use two clients, for example, when one user leaves the chat, the other user can send 1-2 more messages and then the server stops receiving messages from other users, ie there is a known error BrokenpipeError. I understand the terminology of the error, perhaps the error lies on my server in the While True loop (a loop that includes all the actions that users perform with each other) because there is fabulous code in the form of:
if not data:
print(f'User {name1} leave')
break
How can I make the server work under any circumstances and can constantly receive messages from users who leave, log in, stay, etc.? How to make a stream work synchronously without failures? Code 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 (this is for server access):
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()