我的服务器如何知道客户端已断开连接?
Posted
技术标签:
【中文标题】我的服务器如何知道客户端已断开连接?【英文标题】:How does my server know that a client has disconnected? 【发布时间】:2021-12-22 12:16:45 【问题描述】:所以我有一个带有选择的 TCP 连接来处理多个客户端。 这些多个客户端相互聊天,具有独立于服务器的 UDP 连接。 服务器保留所有已连接客户端的列表,并在新客户端到达或断开连接时通知每个客户端。
我有一个工作代码。 我不明白客户端的代码是如何将断开连接信息发送到服务器的。因为服务器收到客户端断开连接的信息。但是如何
server.py:
import pickle
import select
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = ('0.0.0.0', 7000)
server.bind(address)
print('Starting up on %s port %s' % address)
input_sockets = [server]
output_sockets = []
clients = []
server.listen(10)
i = 0
while True:
readable, writable, exceptional = select.select(input_sockets, output_sockets, input_sockets)
for s in readable:
if s is server:
i = i+1
client_socket, client_address = s.accept()
print('New connection from client ' + str(i) + ' with address: ' + str(client_address))
client_socket.send(pickle.dumps(clients))
for client in input_sockets:
if client is not server:
client.send(pickle.dumps(client_address))
input_sockets.append(client_socket)
clients.append(client_address)
else:
client_address = s.getpeername()
print("Client with address '" + str(client_address) + "' disconnected")
clients.remove(client_address)
input_sockets.remove(s)
for client in input_sockets:
if client is not server:
client.send(pickle.dumps(client_address))
s.close()
client.py
import socket
import pickle
import threading
import select
def chat(udp_sock):
global done
while not done:
message = input()
if message == "QUIT":
done = True
else:
for client in clients:
udp_sock.sendto(message.encode('utf-8'), client)
done = False
server_address = ('127.0.0.1', 7000)
s_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s_tcp.connect(server_address)
clients_data = s_tcp.recv(1024)
clients = pickle.loads(clients_data)
s_udp.bind(s_tcp.getsockname())
reading = threading.Thread(target=chat, args=(s_udp,))
reading.start()
while not done:
r, w, e = select.select([s_tcp, s_udp], [], [], 1)
for s in r:
if s == s_tcp:
addr = s_tcp.recv(1024)
addr = pickle.loads(addr)
if addr in clients:
clients.remove(addr)
print("Client " + str(addr) + " has disconnected.")
else:
clients.append(addr)
print("Client " + str(addr) + " is now connected.")
if s == s_udp:
msg, addr = s_udp.recvfrom(1024)
msg = msg.decode()
print("[" + str(addr) + "]: " + str(msg))
reading.join()
s_tcp.close()
s_udp.close()
enter code here
【问题讨论】:
这里有两种可能性: 1. 您编写了代码,并让它工作,但神奇地忘记了您将与服务器断开连接的子句放在哪里。 2. 你从网上拿了随机代码,不明白它的作用,并试图将它拼凑起来做你想做的事,现在不明白它的作用。无论这两者中哪一个是正确的,您都没有在此处提供调试信息,我们甚至无法尝试了解您不理解代码的哪一部分。在撰写本文时,您的问题是“为我解释这段代码?”这是题外话。 【参考方案1】:for s in readable:
if s is server:
...
else:
client_address = s.getpeername()
print("Client with address '" + str(client_address) + "' disconnected")
clients.remove(client_address)
input_sockets.remove(s)
当select
表明它可以从客户端套接字读取时,服务器只是断开客户端的连接。由于客户端从不通过 TCP 连接向服务器发送任何内容,因此客户端套接字可读的唯一情况是客户端断开连接时。在这种情况下,客户端套接字上的 recv
将返回 ''
,即没有数据表明套接字已断开连接。 T
因此,客户端只需断开 TCP 连接,即可向服务器发出客户端已完成的信号。这是通过关闭套接字在代码中显式完成的,但也会在客户端退出时隐式完成。
s_tcp.close()
【讨论】:
以上是关于我的服务器如何知道客户端已断开连接?的主要内容,如果未能解决你的问题,请参考以下文章