![](/img/trans.png)
[英]How do I detect a lost client connection in a server that inherits from pb.Root?
[英]How do I drop a connection if client disconnects from server?
我已经编写了一个服务器和一个客户端,如果我关闭客户端并再次连接,我在服务器上的客户端列表就会堆积起来。 第一次断开连接时,我会打印出列表中的内容,因此首先得到以下信息:
{612: <socket.socket fd=612, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.1.77', 22050), raddr=('192.168.1.77', 53531)>
我第二次连接它只是堆叠起来,所以看起来像这样:
{612: <socket.socket fd=612, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.1.77', 22050), raddr=('192.168.1.77', 53531)>, 620: <socket.socket fd=620, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.1.77', 22050), raddr=('192.168.1.77', 53532)>}
我该如何做才能使它断开连接? 这是服务器代码:
import socket
import threading
from _thread import *
from threading import Thread
clients = {}
def message(c):
while True:
try:
data = c.recv(1024).decode("utf-8")
print("Recieved from: " + str(data))
if not data:
print("Client Disconnected.")
print(clients)
break
# skicka meddelanden till client
for client in clients.values():
try:
if client == c:
continue
client.sendall(data.encode("utf-8"))
except ConnectionAbortedError:
print("[!] Connection aborted ")
print(str(clients))
except ConnectionResetError:
print("[!] Connection reset error ")
print(str(clients))
except ConnectionResetError:
print("[!] - An existing connection was forcibly closed by the remote host. \n")
break
def listener():
host = "192.168.1.77"
port = 22050
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(5)
print("\nServer has started.\n\n" + "Host: " + host + "\nPort: " + str(port))
print("______________________________________________________________________\n")
while True:
c, addr = s.accept()
print(str(addr) + " has connected.")
clients[c.fileno()] = c
threading.Thread(target=message, args=(c,)).start()
if __name__ == '__main__':
listenerthread = Thread(target=listener())
listenerthread.start
#listener()
这是客户端代码:
import socket
import os
from multiprocessing import Process
from threading import Thread
import sys
print("... Awaiting connection from server ...")
host = "192.168.1.77"
port = 22050
try:
s = socket.socket()
s.connect((host, port))
except ConnectionRefusedError:
print("Server is down.")
sys.exit()
try:
print("Connected!")
def send():
while True:
message = input("-> ")
s.send(message.encode("utf-8"))
#recieve = s.recv(1024).decode("utf-8")
#print("- Server: " + recieve)
def recv():
recieve = s.recv(1024).decode("utf-8")
print("\n" + "Server: " + recieve)
# while message !="quitclient":
# s.send(message.encode("utf-8"))
# recieve = s.recv(1024).decode("utf-8")
# print("Recieved from server: " + recieve)
# message = input("-> ")
# s.close()
except ConnectionResetError:
print("Disconnected!")
input("Press enter to exit...")
quit()
sendthread = Thread(target=send)
recvthread = Thread(target=recv)
sendthread.start()
recvthread.start()
客户端代码只是我拥有的GUI客户端代码的cli版本(因为它写的太久了,所以不再写),但是它是相同的代码。 在GUI版本上,我有一个断开按钮, 如下所示:
def Disconnect():
s.shutdown(socket.SHUT_RDWR)
s.close()
我在这里做错了什么?
clients
字典仅添加到,从未删除。 像下面这样的东西应该起作用。 捕获任何异常并退出以从字典中删除密钥。
def message(c):
try:
while True:
data = c.recv(1024).decode("utf-8")
print("Received from: " + str(data))
if not data:
print("Client Disconnected.")
print(clients)
break
# skicka meddelanden till client
for client in clients.values():
if client == c:
continue
client.sendall(data.encode("utf-8"))
except Exception as e:
print(e)
clients.pop(c.fileno())
print(clients)
顺便说一句,由于需要start()
not start
,下面的代码从不启动线程。 侦听器启动是因为在target=listener()
调用了该target=listener()
,该target=listener
应为target=listener
:
if __name__ == '__main__':
listenerthread = Thread(target=listener())
listenerthread.start
#listener()
但是不需要启动线程来调用侦听器。 只需使用:
if __name__ == '__main__':
listener()
您最终还会遇到消息问题。 TCP是一种流协议,因此您不能假定每个recv
都能接收到send
。 send
不能保证将发送每个字节...检查返回值或使用sendall
。 缓慢发送的小消息可能永远不会显示问题,但发送充满多字节UTF-8编码字符的大消息,则会出现错误。 请参阅我的最新答案,以简单的方式解决它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.