在多连接服务器中发生读写事件后,python客户端中的套接字未关闭



我使用的是允许多连接的真实python中的这篇文章。然而,在我使用它后,进行了一个小的更改-

  1. 在发送和接收来自客户端和服务器的消息后,客户端不会关闭;或
  2. 所有的data.messages都已被检查,客户端不关闭

目标是在从服务器和客户端完成所有通信之后close the client

我试过类似sock.settimeout(5.0(的方法,但都不起作用。

看起来这个休息不起作用,这可能是除了设置之外的真正问题:if not sel.get_map(): break

第二,当我检查时,它似乎没有进入这个代码:

if not recv_data:
print("closing connection", data.connid)
sel.unregister(sock)
sock.close()

https://github.com/realpython/materials/blob/master/python-sockets-tutorial/multiconn-client.py

对上述代码的更改如下:

server.py

import sys
import socket
import selectors
import types
sel = selectors.DefaultSelector()
messages = [b"Message 1 from server.", b"Message 2 from server."]
def accept_wrapper(sock):
conn, addr = sock.accept()  # Should be ready to read
print("accepted connection from", addr)
conn.setblocking(False)
data = types.SimpleNamespace(
addr=addr,
inb=b"",
messages=list(messages),
outb=b"",
)
events = selectors.EVENT_READ | selectors.EVENT_WRITE
sel.register(conn, events, data=data)

def service_connection(key, mask):
sock = key.fileobj
data = key.data
if mask & selectors.EVENT_READ:
recv_data = sock.recv(1024)
if recv_data:
data.inb += recv_data
print("received", recv_data, "from", data.addr)
else:
print("closing connection to", data.addr)
sel.unregister(sock)
sock.close()
if mask & selectors.EVENT_WRITE:
if not data.outb and data.messages:
data.outb = data.messages.pop(0)
if data.outb:
print("echoing", repr(data.outb), "to", data.addr)
sent = sock.send(data.outb)
data.outb = data.outb[sent:]

if len(sys.argv) != 3:
print("usage:", sys.argv[0], "<host> <port>")
sys.exit(1)
host, port = sys.argv[1], int(sys.argv[2])
lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.bind((host, port))
lsock.listen()
print("listening on", (host, port))
lsock.setblocking(False)
sel.register(lsock, selectors.EVENT_READ, data=None)
try:
while True:
events = sel.select(timeout=None)
for key, mask in events:
if key.data is None:
accept_wrapper(key.fileobj)
else:
service_connection(key, mask)
except KeyboardInterrupt:
print("caught keyboard interrupt, exiting")
except:
print("uncaught error, exiting")
finally:
sel.close()

client.py

import sys
import socket
import selectors
import types
sel = selectors.DefaultSelector()
messages = [b"Message 1 from client.", b"Message 2 from client."]

def start_connections(host, port, num_conns):
server_addr = (host, port)
for i in range(0, num_conns):
connid = i + 1
print("starting connection", connid, "to", server_addr)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(False)
sock.connect_ex(server_addr)
events = selectors.EVENT_READ | selectors.EVENT_WRITE
data = types.SimpleNamespace(
connid=connid,
recv_total=0,
messages=list(messages),
outb=b"",
inb=b"",
)
sel.register(sock, events, data=data)

def service_connection(key, mask):
sock = key.fileobj
data = key.data
if mask & selectors.EVENT_READ:
recv_data = sock.recv(1024)
print("received", repr(recv_data), "from connection", data.connid)
if recv_data:
data.recv_total += len(recv_data)
data.inb += recv_data
if not recv_data:
print("closing connection", data.connid)
sel.unregister(sock)
sock.close()
if mask & selectors.EVENT_WRITE:
if not data.outb and data.messages:
data.outb = data.messages.pop(0)
if data.outb and data.inb:
print("sending", repr(data.outb), "to connection", data.connid)
sent = sock.send(data.outb)
data.outb = data.outb[sent:]

if len(sys.argv) != 4:
print("usage:", sys.argv[0], "<host> <port> <num_connections>")
sys.exit(1)
host, port, num_conns = sys.argv[1:4]
start_connections(host, int(port), int(num_conns))
try:
while True:
events = sel.select(timeout=1)
if events:
for key, mask in events:
service_connection(key, mask)
else:
break
# Check for a socket being monitored to continue.
if not sel.get_map():
break
except KeyboardInterrupt:
print("caught keyboard interrupt, exiting")
except:
print("uncaught error, exiting")
finally:
sel.close()
sys.exit(1)

这是主REPO TUTS:的原始代码(Echo服务器和客户端(

gitserver.py

#!/usr/bin/env python3
import sys
import socket
import selectors
import types
sel = selectors.DefaultSelector()

def accept_wrapper(sock):
conn, addr = sock.accept()  # Should be ready to read
print("accepted connection from", addr)
conn.setblocking(False)
data = types.SimpleNamespace(addr=addr, inb=b"", outb=b"")
events = selectors.EVENT_READ | selectors.EVENT_WRITE
sel.register(conn, events, data=data)

def service_connection(key, mask):
sock = key.fileobj
data = key.data
if mask & selectors.EVENT_READ:
recv_data = sock.recv(1024)  # Should be ready to read
if recv_data:
data.outb += recv_data
else:
print("closing connection to", data.addr)
sel.unregister(sock)
sock.close()
if mask & selectors.EVENT_WRITE:
if data.outb:
print("echoing", repr(data.outb), "to", data.addr)
sent = sock.send(data.outb)  # Should be ready to write
data.outb = data.outb[sent:]

if len(sys.argv) != 3:
print("usage:", sys.argv[0], "<host> <port>")
sys.exit(1)
host, port = sys.argv[1], int(sys.argv[2])
lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.bind((host, port))
lsock.listen()
print("listening on", (host, port))
lsock.setblocking(False)
sel.register(lsock, selectors.EVENT_READ, data=None)
try:
while True:
events = sel.select(timeout=None)
for key, mask in events:
if key.data is None:
accept_wrapper(key.fileobj)
else:
service_connection(key, mask)
except KeyboardInterrupt:
print("caught keyboard interrupt, exiting")
finally:
sel.close()

gitclient.py

#!/usr/bin/env python3
import sys
import socket
import selectors
import types
sel = selectors.DefaultSelector()
messages = [b"Message 1 from client.", b"Message 2 from client."]

def start_connections(host, port, num_conns):
server_addr = (host, port)
for i in range(0, num_conns):
connid = i + 1
print("starting connection", connid, "to", server_addr)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(False)
sock.connect_ex(server_addr)
events = selectors.EVENT_READ | selectors.EVENT_WRITE
data = types.SimpleNamespace(
connid=connid,
msg_total=sum(len(m) for m in messages),
recv_total=0,
messages=list(messages),
outb=b"",
)
sel.register(sock, events, data=data)

def service_connection(key, mask):
sock = key.fileobj
data = key.data
if mask & selectors.EVENT_READ:
recv_data = sock.recv(1024)  # Should be ready to read
if recv_data:
print("received", repr(recv_data), "from connection", data.connid)
data.recv_total += len(recv_data)
if not recv_data or data.recv_total == data.msg_total:
print("closing connection", data.connid)
sel.unregister(sock)
sock.close()
if mask & selectors.EVENT_WRITE:
if not data.outb and data.messages:
data.outb = data.messages.pop(0)
if data.outb:
print("sending", repr(data.outb), "to connection", data.connid)
sent = sock.send(data.outb)  # Should be ready to write
data.outb = data.outb[sent:]

if len(sys.argv) != 4:
print("usage:", sys.argv[0], "<host> <port> <num_connections>")
sys.exit(1)
host, port, num_conns = sys.argv[1:4]
start_connections(host, int(port), int(num_conns))
try:
while True:
events = sel.select(timeout=1)
if events:
for key, mask in events:
service_connection(key, mask)
# Check for a socket being monitored to continue.
if not sel.get_map():
break
except KeyboardInterrupt:
print("caught keyboard interrupt, exiting")
finally:
sel.close()

我能够使用自定义创建的信号并为其添加句柄代码使其工作。请在下面找到它:

SERVER.PY

import sys
import socket
import selectors
import types
sel = selectors.DefaultSelector()
messages = [b"Server", b"process"]
def accept_wrapper(sock, host, port):
conn, addr = sock.accept()  # Should be ready to read
print("accepted connection from", addr)
conn.setblocking(False)
data = types.SimpleNamespace(
host=host,
port=port,
addr=addr,
recv_total=0,
sent_total=0,
messages=list(messages),
inb=b"",
outb=b"",
)
events = selectors.EVENT_READ | selectors.EVENT_WRITE
sel.register(conn, events, data=data)

def service_connection(key, mask):
sock = key.fileobj
data = key.data
ex = False
if mask & selectors.EVENT_READ:
recv_data = sock.recv(1024)
print("received", repr(recv_data), "from connection", data.addr)
if recv_data:
data.inb += recv_data

if not recv_data and not data.messages:
print("closing connection", data.addr)
sel.unregister(sock)
sock.close()
if (recv_data.decode() == "exit" or "exit" in recv_data.decode()):
ex = True
if mask & selectors.EVENT_WRITE:
if not data.messages and ex:
print("closing connection", data.addr)
sel.unregister(sock)
sock.close()
if not data.outb and data.messages:
data.outb = data.messages.pop(0)
if data.outb:
print("echoing", data.outb, "to", data.addr)
sent = sock.send(data.outb)
data.outb = data.outb[sent:]

if len(sys.argv) != 3:
print("usage:", sys.argv[0], "<host> <port>")
sys.exit(1)
host, port = sys.argv[1], int(sys.argv[2])
lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.bind((host, port))
lsock.listen()
print("listening on", (host, port))
lsock.setblocking(False)
sel.register(lsock, selectors.EVENT_READ, data=None)
try:
while True:
events = sel.select(timeout=None)
for key, mask in events:
if key.data is None:
accept_wrapper(key.fileobj, host, port)
else:
service_connection(key, mask)
except KeyboardInterrupt:
print("caught keyboard interrupt, exiting")
except Exception as e:
print("uncaught error, exiting", e)
finally:
sel.close()

CLIENT.PY

import sys
import socket
import selectors
import types
sel = selectors.DefaultSelector()
messages = [b"Client", b"exit"]
def start_connections(host, port, num_conns):
server_addr = (host, port)
for i in range(0, num_conns):
connid = i + 1
print("starting connection", connid, "to", server_addr)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(False)
sock.connect_ex(server_addr)
events = selectors.EVENT_READ | selectors.EVENT_WRITE
data = types.SimpleNamespace(
connid=connid,
host=host,
port=port,
addr=port,
recv_total=0,
sent_total=0,
messages=list(messages),
inb=b"",
outb=b"",
)
sel.register(sock, events, data=data)

def service_connection(key, mask):
sock = key.fileobj
data = key.data
ex = False
if mask & selectors.EVENT_READ:
recv_data = sock.recv(1024)
print("received", repr(recv_data), "from connection", data.connid)
if recv_data:
data.recv_total += len(recv_data)
data.inb += recv_data

if not recv_data and not data.messages:
print("closing connection", data.connid)
sel.unregister(sock)
sock.close()
if (recv_data.decode() == "exit" or "exit" in recv_data.decode()):
ex = True
if mask & selectors.EVENT_WRITE:
if not data.messages and ex:
print("closing connection", data.connid)
sel.unregister(sock)
sock.close()
if not data.outb and data.messages:
data.outb = data.messages.pop(0)
if data.outb and data.inb:
print("sending", data.outb, "to connection", data.connid)
sent = sock.send(data.outb)
data.outb = data.outb[sent:]    
if len(sys.argv) != 4:
print("usage:", sys.argv[0], "<host> <port> <num_connections>")
sys.exit(1)
host, port, num_conns = sys.argv[1:4]
start_connections(host, int(port), int(num_conns))
try:
while True:
events = sel.select(timeout=1)
if events:
for key, mask in events:
service_connection(key, mask)
else:
break
if not sel.get_map():
break
except KeyboardInterrupt:
print("caught keyboard interrupt, exiting")
except Exception as e:
print("uncaught error, exiting", e)
finally:
sel.close()
sys.exit(1)

最新更新