84 lines
2.5 KiB
Python
84 lines
2.5 KiB
Python
import socket, threading, logging
|
|
|
|
def create_server(port):
|
|
s = Server(port)
|
|
return s.get_backend_fd()
|
|
|
|
class Server:
|
|
def __init__(self, port):
|
|
self.port = port
|
|
self.socket_backend, self.socket_helper = socket.socketpair()
|
|
|
|
self.lock = threading.Lock()
|
|
self.clients = []
|
|
|
|
server_address = ('0.0.0.0', port)
|
|
self.external_server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
|
|
self.external_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
self.external_server.bind(server_address)
|
|
self.external_server.listen()
|
|
|
|
self.start_copying()
|
|
|
|
async_accepter = threading.Thread(target=self.server_accept)
|
|
async_accepter.daemon = True
|
|
async_accepter.start()
|
|
|
|
def get_backend_fd(self):
|
|
return self.socket_backend.fileno()
|
|
|
|
def server_accept(self):
|
|
self.accept_in_loop()
|
|
|
|
def start_copying(self):
|
|
async_writer = threading.Thread(target=self.write_to_clients)
|
|
async_writer.daemon = True
|
|
async_writer.start()
|
|
|
|
def accept_in_loop(self):
|
|
while True:
|
|
try:
|
|
conn, address = self.external_server.accept()
|
|
except Exception as e:
|
|
logging.info("Server: accept error: ", e)
|
|
pass
|
|
|
|
# logging.info("Server: accepted: "+ str(address))
|
|
conn.setblocking(False)
|
|
|
|
self.lock.acquire()
|
|
self.clients.append(conn)
|
|
self.lock.release()
|
|
|
|
async_reader = threading.Thread(target=self.read_from_client, args=(conn,))
|
|
async_reader.daemon = True
|
|
async_reader.start()
|
|
|
|
def read_from_client(self, conn):
|
|
while True:
|
|
try:
|
|
data = conn.recv(1024)
|
|
if data:
|
|
# logging.info("Server: in: "+ str(data))
|
|
self.socket_helper.sendall(data)
|
|
except Exception as e:
|
|
""
|
|
|
|
def write_to_clients(self):
|
|
while True:
|
|
self.lock.acquire()
|
|
clients = self.clients
|
|
self.lock.release()
|
|
|
|
if len(clients) == 0:
|
|
continue
|
|
|
|
try:
|
|
data = self.socket_helper.recv(1024)
|
|
if data:
|
|
# logging.info("Server: out: "+ str(data))
|
|
for c in clients:
|
|
c.sendall(data)
|
|
except Exception as e:
|
|
""
|