[英]Socket not shutting down/closing (python3)
我有一個server
變量,它是套接字 object。
出於某種原因,當我執行server.shutdown(socket.SHUT_RDWR)
時,它給了我以下錯誤:
OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
我嘗試使用.close()
,但它給了我這個:
OSError: [WinError 10038] an operation was attempted on something that is not a socket
服務器代碼:
import sys
import time
import socket
import threading
import tkinter as tk
from tkinter import messagebox as msgbox
HEADER = 64
PORT = 5050
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "%client_disconnect"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
server_active = True
messages = []
def add_message(message):
local_t = time.localtime()
sent_at = time.strftime("%Y.%m.%d %H:%M:%S", local_t)
messages.append(f"{sent_at} | {str(message)}")
def handle_client(conn, addr):
print(f"\n===[DEBUG (SERVER)]\tHandling connection: {addr}")
connected = True
while connected:
msg_len = conn.recv(HEADER).decode(FORMAT)
if msg_len:
msg_len = int(msg_len)
msg = conn.recv(msg_len).decode(FORMAT)
print(f"\n===[DEBUG ({addr})]\tMessage length: {msg_len}; Message: {msg}")
if msg == DISCONNECT_MESSAGE:
connected = False
if not server_active:
connected = False
conn.close()
def start():
server.listen()
print(f"\n===[DEBUG (SERVER)]\tListening on {SERVER}")
while True:
print("\n===[DEBUG (SERVER)]\tWaiting for client connection")
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"\n===[DEBUG (SERVER)]\tNew connection: ({addr}); "
f"Current active connections: {threading.active_count() - 1}")
def on_closing():
global server_active
if msgbox.askokcancel("Serverside", "Are you sure you want to quit? This will fully shut down the server"
"and disconnect all clients."):
server_active = False
window.destroy()
server.close()
# window is empty
window = tk.Tk()
window.wm_geometry("700x500")
window.title("Serverside")
window.protocol("WM_DELETE_WINDOW", on_closing)
t = time.localtime()
start_time = time.strftime("%Y.%m.%d %H:%M:%S", t)
print("===[DEBUG (SERVER)]\tStarting Server")
server_thread = threading.Thread(target=start)
server_thread.start()
add_message(f"Server started at: {start_time}")
tk.mainloop()
客戶端代碼:
import socket
import threading
import tkinter as tk
from tkinter import messagebox as msgbox
HEADER = 64
PORT = 5050
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "%client_disconnect"
SERVER = None
ADDR = None
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def send(msg):
message = msg.encode(FORMAT)
msg_len = len(message)
send_len = str(msg_len).encode(FORMAT)
send_len += b' ' * (HEADER - len(send_len))
client.send(send_len)
client.send(message)
def connect_to(server):
global SERVER, ADDR
SERVER = server
ADDR = (SERVER, PORT)
client.connect(ADDR)
def on_closing():
if msgbox.askokcancel("Client", "Are you sure you want to quit? You will be disconnected from the server."):
send(DISCONNECT_MESSAGE)
window.destroy()
def handle_messages():
msg = str(entry.get())
send(msg)
if msg == DISCONNECT_MESSAGE:
window.destroy()
connect_to(socket.gethostbyname(socket.gethostname()))
window = tk.Tk()
window.geometry("600x450")
window.title("Client")
window.protocol("WM_DELETE_WINDOW", on_closing)
entry = tk.Entry()
entry.place(x=0, y=0, width=100, height=30)
button = tk.Button(command=handle_messages)
button.place(x=0, y=50, width=50, height=20)
tk.mainloop()
也許我錯誤地關閉了服務器?
所以這個錯誤有點奇怪。 您正在正確關閉套接字,但沒有正確處理線程。
發生的事情是您的start thread
接受新連接,但您正在關閉主線程上的套接字。 所以發生的事情是主線程關閉套接字,但start thread
仍在接受連接,但由於套接字已關閉,它會拋出該錯誤。 這個錯誤沒什么大不了的,你可以忽略它,如果你想要或者包裹在一個 catch 中,然后跳出 while 循環,或者你可以在關閉套接字之前加入你的線程,然后就沒有更多的錯誤了。
需要注意兩點:
這是修改后的代碼,以避免使用超時的錯誤。
def start():
server.listen()
print(f"\n===[DEBUG (SERVER)]\tListening on {SERVER}")
while True:
print("\n===[DEBUG (SERVER)]\tWaiting for client connection")
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr), daemon=True) # This is a daemon thread now
thread.start()
print(f"\n===[DEBUG (SERVER)]\tNew connection: ({addr}); "
f"Current active connections: {threading.active_count() - 1}")
...
def on_closing():
global server_active
if msgbox.askokcancel("Serverside", "Are you sure you want to quit? This will fully shut down the server"
"and disconnect all clients."):
server_active = False
window.destroy()
server_thread.join(timeout=0.0) # Timeout the thread to force it to join
server.close()
...
server_thread = threading.Thread(target=start, daemon=True) # I'm a daemon thread so i dont block the program from closing
server_thread.start()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.