哪几条有数据
三条连接里第 0、2 条发了数据,ready 交回什么?
贯穿全条的内存版 TCP(判题机不联网;接口和真 socket 一样,真机上换成 socket.socket() 就是真的):net = Net();lis = listen(net, 端口) 开监听;cli = connect(net, 端口) 客户端连上(交回客户端这头,服务端那头进 accept 队列);srv = lis.accept() 领一条连接;sendall 把字节追加进对面收缓冲,recv(n) 从自己收缓冲取最多 n 字节(拿到多少算多少,recv 交回 b"" 表示对面关了)。
多客户端(单线程轮询):ready(srvs) 交回收缓冲有数据的连接下标;serve_ready(srvs) 给每条有数据的各回一段(echo)、交回处理过的下标。
import collections
class Net:
def __init__(self):
self.listeners = {}
class Endpoint:
def __init__(self, name):
self.name = name
self.rbuf = b""
self.peer = None
self.peer_closed = False
self.closed = False
def send(self, data):
if self.closed or self.peer is None:
raise BrokenPipeError("连接已关")
self.peer.rbuf += bytes(data)
return len(data)
def sendall(self, data):
self.send(data)
def recv(self, bufsize):
if self.rbuf:
out, self.rbuf = self.rbuf[:bufsize], self.rbuf[bufsize:]
return out
if self.peer_closed:
return b""
raise BlockingIOError("暂时没有数据(真 socket 会在这里阻塞等)")
def close(self):
self.closed = True
if self.peer is not None:
self.peer.peer_closed = True
class Listener:
def __init__(self):
self.backlog = collections.deque()
def accept(self):
if not self.backlog:
raise BlockingIOError("暂时没有新连接")
return self.backlog.popleft()
def listen(net, port):
lis = Listener()
net.listeners[port] = lis
return lis
def connect(net, port):
if port not in net.listeners:
raise ConnectionRefusedError(111, "Connection refused")
cli = Endpoint("client")
srv = Endpoint("server")
cli.peer = srv
srv.peer = cli
net.listeners[port].backlog.append(srv)
return cli
def ready(srvs):
# 交回收缓冲里有数据的那几条连接的下标
return [i for i, s in enumerate(srvs) if s.rbuf]
def serve_ready(srvs):
# 给每条有数据的连接各回一段(echo),交回处理过的下标
done = []
for i, s in enumerate(srvs):
if s.rbuf:
s.sendall(s.recv(4096))
done.append(i)
return done
net = Net()
lis = listen(net, 9000)
conns = [connect(net, 9000) for _ in range(3)]
srvs = [lis.accept() for _ in range(3)]
conns[0].sendall(b"x")
conns[2].sendall(b"z")
print(",".join(str(i) for i in ready(srvs)))
全部评论