如何从服务器发送请求断开连接到所有客户端和服务器仍然存在(python套接字)

Posted

技术标签:

【中文标题】如何从服务器发送请求断开连接到所有客户端和服务器仍然存在(python套接字)【英文标题】:How to send request disconnect from server to all clients and server still live (python socket) 【发布时间】:2022-01-21 18:15:51 【问题描述】:

当我断开服务器中的所有客户端时,服务器无法继续运行。直播服务器怎么办

import socket, threading, tkinter

服务器

import socket, threading, tkinter
import time

def sendDisconnectAll(my_clients):
    for client in my_clients:
        conn = client[0]
        conn.sendall('Disconnect'.encode('utf8'))
        conn.close()
    
def handle_client(conn, addr):
    while True:
        try:
            request_from_clients = conn.recv(1024).decode('utf8') #sample request
            print(request_from_clients)
            if request_from_clients == 'SignIn':
                conn.sendall('Accept Sign in'.encode('utf8'))
        except:
            print('Client has been shutdown')
            break

my_clients = []
def live_server():
    global thr
    global s
    while True:
        try:
            conn, addr = s.accept()
            my_clients.append((conn, addr))
            thr = threading.Thread(target=handle_client, args=(conn, addr))
            thr.daemon = True
            thr.start()
        except:
            print("Error")

HOST = '127.0.0.1'
PORT = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen()
print('HOST: ', HOST)
print('PORT: ', PORT)

thr = threading.Thread(target=live_server)
thr.daemon = True
thr.start()
count_time = time.time()
while True:
    now = time.time()
    if (int(now - count_time) + 1) % 10 == 0:       #Disconnect all clients after 10 seconds
        count_time = now
        request = 'Disconnect'
        print('Disconnect all')
        sendDisconnectAll(my_clients)

客户

import socket, threading
import tkinter as tk
from tkinter import *

def signIn():
    global client
    request = 'SignIn'
    try:
        client.sendall(request.encode('utf8'))
        client.recv(1024).decode('utf8')
    except:
        print('Server has been shutdown')

IP = input("Enter IP: ")
PORT = input("Enter PORT: ")

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    client.connect((IP, int(PORT)))
except:
    print("Can't connect to server")
    client.close()
def live_client():
    global client
    while True:
        print(client.recv(1024).decode('utf8'))
thr = threading.Thread(target=live_client)
thr.daemon = True
thr.start()
app = Tk()
app.title('CLIENT')
but_connect = tk.Button(app, text="SIGN IN",
                            width=20, command=signIn)
but_connect.pack(pady=6)
app.mainloop()

谢谢!

【问题讨论】:

您通过关闭套接字来切断连接,但客户端不会收到此通知。如果他们有一个读取挂起,读取将返回 0 个字节。 服务器可以在关闭所有客户端套接字之前向客户端发送一些数据。 我尝试在关闭服务器源代码中的客户端套接字之前向客户端发送请求“断开连接”,并使客户端在“While True:”中接收来自服务器的请求“断开连接”,但它不起作用。 @蒂姆罗伯茨 我尝试在关闭服务器源代码中的客户端套接字之前向客户端发送请求“断开连接”,并使客户端在“While True:”中接收来自服务器的请求“断开连接”,但它不起作用。 @acw1668 您的客户正在阅读,对吧?您的示例代码没有显示。 【参考方案1】:

问题在于您只将客户端添加到my_clients 列表中。让我们看看服务器中发生了什么:

服务器启动 它接收一个客户并将其添加到my_clients 在下一个全部断开操作时,该客户端的套接字已关闭,但该客户端仍保留在列表中 在接下来的全部断开操作中,服务器的主线程尝试写入已关闭的套接字并引发异常 由于所有其他线程都是守护线程,因此应用程序结束。

您必须在关闭所有客户端套接字后清除my_clients 列表:

def sendDisconnectAll(my_clients):
    for client in my_clients:
        conn = client[0]
        conn.sendall('Disconnect'.encode('utf8'))
        conn.close()
    my_clients.clear()

注意:我没有看客户端代码...

【讨论】:

我的问题解决了!谢谢!

以上是关于如何从服务器发送请求断开连接到所有客户端和服务器仍然存在(python套接字)的主要内容,如果未能解决你的问题,请参考以下文章

尽管用户未连接到服务器,但用户仍处于联机状态。并且无法重新连接到服务器

C# 如何向连接到我的服务器的所有客户端发送数据?

C# - 关于服务器向客户端发送推送通知的设计问题 - 如何实现?

服务器端的服务器发送事件成本

断开Qt后连接到服务器时客户端程序崩溃

Socket.io 客户端在突然断开连接后无法重新连接到服务器