套接字上的 BrokenPipeError
Posted
技术标签:
【中文标题】套接字上的 BrokenPipeError【英文标题】:BrokenPipeError on socket 【发布时间】:2021-12-24 08:28:19 【问题描述】:我使用 Python Socket 创建了一个信使,当我使用两个客户端时,例如,当一个用户离开聊天时,第二个用户可以再发送 1-2 条消息,之后服务器停止接受来自其他用户的消息,即是否有一个众所周知的错误 Broken pipe 32. 我理解错误的术语,也许错误在于我的服务器上的 While True 循环(一个包含用户之间执行的所有操作的循环),因为有是一个美妙的代码形式:
if not data:
print(f'User name1 leave')
break
但我需要它,因为没有它服务器会直接飞走,如果做出类似的机制,服务器仍然可以接收来自用户的信息。
希望相互理解,任何帮助都会被接受和感激。服务器和客户端代码如下:
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()
客户:
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()
【问题讨论】:
请将您的代码减少到重现问题所需的绝对最低限度 - 可能不需要 tkinter GUI 和加密转换。另外请准确描述如何使用代码重现问题以及错误实际发生的位置(客户端还是服务器?) Steffen,这里的问题不是加密或 GUI,而是 While True 循环上的服务器。我需要收到用户离开聊天的消息,但如果我设置“如果不是数据:中断”,服务器将停止接收消息,如果此命令不是,服务器将简单地开始写入“约翰发送”消息:' “这里的问题不是加密或 GUI” - 完全正确。并且由于这些代码部分不需要重现问题。请尽量减少您提供的代码。见How to create a Minimal, Reproducible Example。 如果您愿意提供帮助,我将在此处保留没有 GUI 的最小客户端和存在相同错误的同一服务器。但是客户端在这里没用,我把它扔了,你可以进去看看如何修复错误。 【参考方案1】:也许错误在于我的服务器上的 While True 循环(一个包含用户之间执行的所有操作的循环),因为表单中有一段很棒的代码:
if not data: print(f'User name1 leave') break
您已经发现了错误原因所在的位置。发生错误是因为服务器不断尝试发送到断开连接的客户端(在该代码上方的循环中)。要阻止服务器尝试此操作,您只需在您识别断开连接的位置从sort
(已连接客户端列表)中删除客户端,即。 e.在break
之前插入sort.remove(user)
。
【讨论】:
朋友,非常感谢您的帮助和理解。你不知道我为解决这个问题做了多少不同的操作。非常感谢你,我注意到你的回答是最好的,因为你不仅帮助解决了一个我没有注意到的小问题,还帮助我重新享受生活,晚上睡觉)以上是关于套接字上的 BrokenPipeError的主要内容,如果未能解决你的问题,请参考以下文章