[英]How do I drop a connection if client disconnects from server?
I have written a server and a client and if I close my client and connect again my clients list on the server just stacks up. 我已经编写了一个服务器和一个客户端,如果我关闭客户端并再次连接,我在服务器上的客户端列表就会堆积起来。 First time I disconnect I print out whats on the list so first I get this:
第一次断开连接时,我会打印出列表中的内容,因此首先得到以下信息:
{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)>
Second time I connect it just stacks up so it looks like this: 我第二次连接它只是堆叠起来,所以看起来像这样:
{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)>}
How do I make it so it just drops the connection? 我该如何做才能使它断开连接? Here is the server code:
这是服务器代码:
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()
And here is the client code: 这是客户端代码:
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()
The client code is just a cli version of the GUI client code I have (not writing it since its way too long) but its the same code. 客户端代码只是我拥有的GUI客户端代码的cli版本(因为它写的太久了,所以不再写),但是它是相同的代码。 On the GUI version I have a disconnect button that looks like this:
在GUI版本上,我有一个断开按钮, 如下所示:
def Disconnect():
s.shutdown(socket.SHUT_RDWR)
s.close()
What am I doing wrong here? 我在这里做错了什么?
The clients
dictionary is only added to, never removed. clients
字典仅添加到,从未删除。 Something like the following should work. 像下面这样的东西应该起作用。 Catch any exception and drop out to remove the key from the dictionary.
捕获任何异常并退出以从字典中删除密钥。
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)
As an aside, the code below never starts a thread due to needing start()
not start
. 顺便说一句,由于需要
start()
not start
,下面的代码从不启动线程。 The listener starts because it is called in target=listener()
, which should be target=listener
: 侦听器启动是因为在
target=listener()
调用了该target=listener()
,该target=listener
应为target=listener
:
if __name__ == '__main__':
listenerthread = Thread(target=listener())
listenerthread.start
#listener()
But starting a thread to call listener is not needed. 但是不需要启动线程来调用侦听器。 Just use:
只需使用:
if __name__ == '__main__':
listener()
You'll also eventually have a problem with messages. 您最终还会遇到消息问题。 TCP is a streaming protocol, so you can't assume each
recv
receive exactly what send
sent. TCP是一种流协议,因此您不能假定每个
recv
都能接收到send
。 send
doesn't guarantee it will send every byte either...check the return value or use sendall
. send
不能保证将发送每个字节...检查返回值或使用sendall
。 Small messages sent slowly may never show the problem, but send large messages full of multi-byte UTF-8-encoded characters and you'll get an error. 缓慢发送的小消息可能永远不会显示问题,但发送充满多字节UTF-8编码字符的大消息,则会出现错误。 See this recent answer of mine for a simple way to solve it.
请参阅我的最新答案,以简单的方式解决它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.