Skip to content

Instantly share code, notes, and snippets.

@remittor
Last active March 22, 2023 10:34
Show Gist options
  • Save remittor/f2c89f50ff259e6e704fe246ee6c3dd5 to your computer and use it in GitHub Desktop.
Save remittor/f2c89f50ff259e6e704fe246ee6c3dd5 to your computer and use it in GitHub Desktop.
pl_test.py
import sys
import io
import time
import datetime
import socket
import asyncore
import struct
import optparse
parser = optparse.OptionParser("usage: %prog [options]", add_help_option=False)
parser.add_option("-h", "--host", dest="host", default='127.0.0.1', type="string")
parser.add_option("-p", "--port", dest="port", default=5000, type="int")
parser.add_option("-u", "--url", dest="url", default="/", type="string")
parser.add_option("-@", "--shorttest", dest="shorttest", action="store_true", default=False)
parser.add_option("-#", "--chunknum", dest="chunknum", default=3, type="int")
(opt, args) = parser.parse_args()
def get_request(path = r'/', host = '127.0.0.1', port = 5000):
req = f'GET {path}' + r' HTTP/1.1' + '\r\n'
req += f'Host: {host}:{port}\r\n'
req += r'User-Agent: curl/7.66.0' + '\r\n'
#req += r'Accept: */*' + '\r\n'
req += r'Accept: text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7' + '\r\n'
req += r'Connection: keep-alive' + '\r\n'
req += '\r\n'
return req.encode('utf8')
payload_base = get_request(path = opt.url, host = opt.host, port = opt.port)
payload_size = len(payload_base)
def create_sock(timeout = 0.1):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
sock.connect((opt.host, opt.port))
return sock
print(f'base payload size = {len(payload_base)} (0x%X)' % len(payload_base))
payload = payload_base * opt.chunknum
chunk_size = payload_size * (opt.chunknum - 1) + payload_size // 2
resp = b''
sock = create_sock(1)
sock.sendall(payload[0:chunk_size])
time.sleep(0.1)
try:
resp += sock.recv(4096)
except socket.timeout:
pass
print(f'recv preload size = {len(resp)}')
sock.sendall(payload[chunk_size: ])
time.sleep(0.1)
try:
resp += sock.recv(4096)
except socket.timeout:
print(resp.decode('utf-8'))
raise
print('total resp size =', len(resp))
print(resp)
print('====== response ========')
print(resp.decode('utf-8'))
print('========================')
sock.close()
g_resp_size = len(resp) // opt.chunknum
print(f'Test 0 completed! {opt.chunknum=}')
if opt.shorttest:
sys.exit(0)
# =================================================================
start_time = datetime.datetime.now()
test1_limit = start_time + datetime.timedelta(seconds = 1)
test2_limit = test1_limit + datetime.timedelta(minutes = 10)
totalrecv = 0
sock = create_sock()
while True:
if datetime.datetime.now() >= test1_limit:
break
sock.sendall(payload_base)
try:
resp = sock.recv(4096)
totalrecv += len(resp)
except socket.timeout:
pass
print(f'Test 1 completed! {totalrecv=}')
sock.close()
# =================================================================
print(f'Run test 2 ...')
req_num = 10*1000*1000
#req_num = 1000
payload_huge = payload_base * req_num
print(f'payload_huge = {len(payload_huge)} bytes')
g_expected_recv = g_resp_size * req_num
class HttpClient(asyncore.dispatcher):
def __init__(self, buffer):
asyncore.dispatcher.__init__(self)
self.create_socket()
self.connect( (opt.host, opt.port) )
self.buffer = buffer
self.totalsent = 0
self.totalrecv = 0
self.lastresp = b''
self.show_time = datetime.datetime.now()
def handle_connect(self):
self.show_time = datetime.datetime.now()
def handle_close(self):
print(f'totalrecv = {self.totalrecv}')
print('Close HTTP client')
self.close()
def handle_read(self):
resp = self.recv(65*1024)
self.totalrecv += len(resp)
if len(resp) == 0:
raise "Remote peer disconnected."
self.lastresp = resp
#print('>>>', resp)
if resp.find(b'HTTP/1.1 4') >= 0 or resp.find(b'HTTP/1.1 5') >= 0:
raise '==== BAD Request ====='
if self.show_time <= datetime.datetime.now():
self.show_time = datetime.datetime.now() + datetime.timedelta(seconds = 2)
print(f'totalrecv = {self.totalrecv}')
if self.totalrecv >= g_expected_recv - g_resp_size * 4:
self.handle_close()
def writable(self):
return True if (self.totalsent < len(self.buffer)) else False
def handle_write(self):
sent = self.send(self.buffer[self.totalsent:])
self.totalsent += sent
if sent > 0:
print(f'sent = {sent} totalsent = {self.totalsent}')
#if self.totalsent >= len(self.buffer):
# self.handle_close()
client = HttpClient(payload_huge)
asyncore.loop()
#asyncore.loop(use_poll = True)
print("==== Test Finish =====")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment