The key to high performance as you rightly pointed out was preventing flushing. In the end, what worked best was reducing the number of writes to disk (which is the bottleneck). I did that by buffering 10-50 ms worth of TCP data, coupled with only flushing explicitly (using a large buffer so that neither BinaryWriter or FileStream flush automatically).
import socket import win32pipe import win32file import sys
BUFFER_SIZE = 4096
def create_pipe(pipe_name): return win32pipe.CreateNamedPipe(pipe_name, win32pipe.PIPE_ACCESS_DUPLEX, win32pipe.PIPE_TYPE_BYTE | win32pipe.PIPE_READMODE_BYTE | win32pipe.PIPE_WAIT, 1, BUFFER_SIZE, BUFFER_SIZE, 0, None)
def open_pipe(pipe_name): return win32file.CreateFile(pipe_name, win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0, None, win32file.OPEN_EXISTING, 0, None)
def proxy_server(machine_name): server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('0.0.0.0', 8080)) server_socket.listen(1)
pipe_name_1 = r'\\' + machine_name + r'\pipe\proxy_pipe_1'
pipe_name_2 = r'\\' + machine_name + r'\pipe\proxy_pipe_2'
while True:
client_socket, _ = server_socket.accept()
pipe_1, pipe_2 = create_pipe(pipe_name_1), create_pipe(pipe_name_2)
win32pipe.ConnectNamedPipe(pipe_1, None)
win32pipe.ConnectNamedPipe(pipe_2, None)
while True:
data = client_socket.recv(BUFFER_SIZE)
if not data:
break
win32file.WriteFile(pipe_1, data)
response = win32file.ReadFile(pipe_2, BUFFER_SIZE)[1]
client_socket.send(response)
client_socket.close()
win32file.CloseHandle(pipe_1)
win32file.CloseHandle(pipe_2)
def proxy_client(server_name, machine_name):
target_host, target_port = 'cnn.com', 80 pipe_name_1 = r'\\' + server_name + r'\pipe\proxy_pipe_1_' + machine_name
pipe_name_2 = r'\\' + server_name + r'\pipe\proxy_pipe_2_' + machine_name
pipe_1, pipe_2 = open_pipe(pipe_name_1), open_pipe(pipe_name_2)
target_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
target_socket.connect((target_host, target_port))
while True:
data = win32file.ReadFile(pipe_1, BUFFER_SIZE)[1]
if not data:
break
target_socket.send(data)
response = target_socket.recv(BUFFER_SIZE)
win32file.WriteFile(pipe_2, response)
target_socket.close()
win32file.CloseHandle(pipe_1)
win32file.CloseHandle(pipe_2)
if __name__ == '__main__':
if len(sys.argv) < 3:
print("Usage: python script.py [server|client] [machine_name] [server_name (for client only)]")
sys.exit(1) mode, machine_name = sys.argv[1], sys.argv[2]
if mode == 'server':
proxy_server(machine_name)
elif mode == 'client':
if len(sys.argv) < 4:
print("Please provide the server name or IP address for the client mode.")
sys.exit(1)
server_name = sys.argv[3]
proxy_client(server_name, machine_name)
else:
print("Invalid mode. Please use 'server' or 'client'.")
sys.exit(1)