mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-17 08:55:49 +08:00
82 lines
2.1 KiB
Python
82 lines
2.1 KiB
Python
"""Does closing with unread data reset the connection, and is the reply lost?
|
|
|
|
The server reads only part of a large upload, answers, and closes in one of
|
|
three ways while the client is still sending. The client reports how much of
|
|
the reply arrived and what errors it saw.
|
|
"""
|
|
import socket, sys, threading, time
|
|
|
|
REPLY = b"R" * 65536
|
|
UPLOAD = 1500000
|
|
|
|
|
|
def server(lsock, variant):
|
|
c, _ = lsock.accept()
|
|
got = 0
|
|
while got < 16384:
|
|
d = c.recv(16384 - got)
|
|
if not d:
|
|
break
|
|
got += len(d)
|
|
c.sendall(REPLY)
|
|
if variant == "close":
|
|
c.close()
|
|
elif variant == "shutrdwr":
|
|
c.shutdown(socket.SHUT_RDWR)
|
|
c.close()
|
|
elif variant == "drain":
|
|
c.shutdown(socket.SHUT_WR)
|
|
c.settimeout(5)
|
|
try:
|
|
while c.recv(65536):
|
|
pass
|
|
except OSError:
|
|
pass
|
|
c.close()
|
|
|
|
|
|
def run(variant):
|
|
lsock = socket.socket()
|
|
lsock.bind(("127.0.0.1", 0))
|
|
lsock.listen(1)
|
|
port = lsock.getsockname()[1]
|
|
t = threading.Thread(target=server, args=(lsock, variant))
|
|
t.start()
|
|
cl = socket.create_connection(("127.0.0.1", port))
|
|
errs = {}
|
|
|
|
def send():
|
|
try:
|
|
cl.sendall(b"x" * UPLOAD)
|
|
cl.shutdown(socket.SHUT_WR)
|
|
except OSError as e:
|
|
errs["send"] = type(e).__name__
|
|
|
|
st = threading.Thread(target=send)
|
|
st.start()
|
|
# read slowly at first, as a client busy uploading would
|
|
time.sleep(0.3)
|
|
rx = 0
|
|
cl.settimeout(5)
|
|
try:
|
|
while True:
|
|
d = cl.recv(65536)
|
|
if not d:
|
|
break
|
|
rx += len(d)
|
|
except OSError as e:
|
|
errs["recv"] = type(e).__name__
|
|
st.join()
|
|
t.join()
|
|
cl.close()
|
|
lsock.close()
|
|
return rx, errs
|
|
|
|
|
|
for variant in sys.argv[1:] or ["close", "shutrdwr", "drain"]:
|
|
results = [run(variant) for _ in range(5)]
|
|
full = sum(1 for rx, _ in results if rx == len(REPLY))
|
|
errs = sorted({k + ":" + v for _, e in results for k, v in e.items()})
|
|
print("%-9s reply complete %d/5, received %s, errors %s"
|
|
% (variant, full, [rx for rx, _ in results], errs or "none"))
|