100 lines
2.9 KiB
Python
100 lines
2.9 KiB
Python
|
import datetime
|
||
|
import random
|
||
|
import socket
|
||
|
import string
|
||
|
import threading
|
||
|
import time
|
||
|
|
||
|
BUFFER_SIZE = 2048
|
||
|
ENCODING = 'ascii'
|
||
|
|
||
|
threads = {}
|
||
|
to_join = []
|
||
|
|
||
|
|
||
|
def string_generator(size=6, chars=string.ascii_uppercase + string.digits):
|
||
|
return ''.join(random.choice(chars) for _ in range(size))
|
||
|
|
||
|
|
||
|
class HandleClientConnectionThread(threading.Thread):
|
||
|
""" Handle requests given by the client """
|
||
|
|
||
|
def __init__(self, connection, client_address, id, msg_size):
|
||
|
threading.Thread.__init__(self)
|
||
|
self.connection = connection
|
||
|
self.client_address = client_address
|
||
|
self.id = id
|
||
|
self.msg_size = msg_size
|
||
|
self.delays = []
|
||
|
|
||
|
def run(self):
|
||
|
try:
|
||
|
print(self.id, ": Connection from", self.client_address)
|
||
|
start_time = None
|
||
|
buffer_data = ""
|
||
|
|
||
|
# Receive the data and retransmit it
|
||
|
while True:
|
||
|
data = self.connection.recv(BUFFER_SIZE).decode(ENCODING)
|
||
|
|
||
|
if len(data) == 0:
|
||
|
# Connection closed at remote; close the connection
|
||
|
break
|
||
|
|
||
|
buffer_data += data
|
||
|
|
||
|
if len(buffer_data) == self.msg_size:
|
||
|
stop_time = datetime.datetime.now()
|
||
|
if start_time:
|
||
|
self.delays.append(stop_time - start_time)
|
||
|
time.sleep(5.0)
|
||
|
response = string_generator(size=self.msg_size, chars=string.digits)
|
||
|
start_time = datetime.datetime.now()
|
||
|
self.connection.sendall(response).encode(ENCODING)
|
||
|
buffer_data = ""
|
||
|
|
||
|
elif len(buffer_data) > self.msg_size:
|
||
|
print("Too much data; break")
|
||
|
break
|
||
|
|
||
|
finally:
|
||
|
# Clean up the connection
|
||
|
print(self.id, ": Closing connection")
|
||
|
self.connection.close()
|
||
|
print(self.delays)
|
||
|
to_join.append(self.id)
|
||
|
|
||
|
|
||
|
def join_finished_threads():
|
||
|
""" Join threads whose connection is closed """
|
||
|
while len(to_join) > 0:
|
||
|
thread_to_join_id = to_join.pop()
|
||
|
threads[thread_to_join_id].join()
|
||
|
del threads[thread_to_join_id]
|
||
|
|
||
|
# Create a TCP/IP socket
|
||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||
|
# Handle reusing the same 5-tuple if the previous one is still in TIME_WAIT
|
||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||
|
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||
|
|
||
|
# Bind the socket to the port
|
||
|
server_address = ('0.0.0.0', 8000)
|
||
|
print("Stating the server on %s port %s" % server_address)
|
||
|
sock.bind(server_address)
|
||
|
|
||
|
# Listen for incoming connections
|
||
|
sock.listen(4)
|
||
|
|
||
|
# Connection identifier
|
||
|
conn_id = 0
|
||
|
|
||
|
while True:
|
||
|
# Wait for a connection
|
||
|
connection, client_address = sock.accept()
|
||
|
thread = HandleClientConnectionThread(connection, client_address, conn_id, 1200)
|
||
|
threads[conn_id] = thread
|
||
|
conn_id += 1
|
||
|
thread.start()
|
||
|
join_finished_threads()
|