This commit is contained in:
2026-02-19 10:14:42 +08:00
parent 9d91a77647
commit f1cde528a4
6 changed files with 78 additions and 107 deletions

View File

@@ -1,41 +0,0 @@
defmodule AlterProxy do
def start(port) do
# 監聽端口
{:ok, listen_socket} =
:gen_tcp.listen(port, [
:binary,
packet: :line,
reuseaddr: true,
active: false,
backlog: 100
])
spawn(__MODULE__, :accept_loop, [listen_socket])
listen_socket
end
def accept_loop(listen_socket) do
case :gen_tcp.accept(listen_socket) do
{:ok, socket} ->
spawn(__MODULE__, :handle_client, [socket])
accept_loop(listen_socket)
{:error, reason} ->
IO.puts("接受連接失敗: #{reason}")
end
end
def handle_client(socket) do
# 接收數據
case :gen_tcp.recv(socket, 0) do
{:ok, data} ->
IO.puts("收到: #{data}")
:gen_tcp.send(socket, "Echo: #{data}")
# 繼續接收
handle_client(socket)
{:error, :closed} ->
IO.puts("客戶端斷開連接")
end
end
end

View File

@@ -1,33 +1,21 @@
defmodule Broker do defmodule Broker do
use GenServer use GenServer
def init({protocol, port, to_host, to_port}) do def start_link({:tcp, port, to_host, to_port}) do
GenServer.start_link(__MODULE__, {:tcp, port, to_host, to_port})
end
@impl true
def init({:tcp, port, to_host, to_port}) do
{:ok, listen_socket} = {:ok, listen_socket} =
:gen_tcp.listen(port, [ :gen_tcp.listen(port, [
:binary, :binary,
reuseaddr: true, reuseaddr: true,
active: false, active: true,
backlog: 100 backlog: 100
]) ])
{:ok, TcpWatcher.start_link({to_host, to_port, listen_socket})
%{ {:ok, {:tcp, port, to_host, to_port, listen_socket}}
protocol: protocol,
port: port,
to_host: to_host,
to_port: to_port,
listen_socket: listen_socket
}}
end
def accept_loop(listen_socket) do
case :gen_tcp.accept(listen_socket) do
{:ok, socket} ->
spawn(__MODULE__, :handle_client, [socket])
accept_loop(listen_socket)
{:error, reason} ->
IO.puts("接受連接失敗: #{reason}")
end
end end
end end

View File

@@ -10,8 +10,12 @@ defmodule Manager do
DynamicSupervisor.init(strategy: :one_for_one) DynamicSupervisor.init(strategy: :one_for_one)
end end
def create_broker(port) do def create_broker(protocol, port, to_host, to_port) do
spec = {Broker, port} spec = {Broker, {protocol, port, to_host, to_port}}
DynamicSupervisor.start_child(__MODULE__, spec) DynamicSupervisor.start_child(__MODULE__, spec)
end end
def list_brokers() do
DynamicSupervisor.which_children(__MODULE__)
end
end end

View File

@@ -1,43 +0,0 @@
defmodule TcpHandler do
def start(port) do
# 監聽端口
{:ok, listen_socket} =
:gen_tcp.listen(port, [
:binary,
packet: :line,
reuseaddr: true,
active: false,
backlog: 100
])
accept_loop(listen_socket)
end
defp accept_loop(listen_socket) do
case :gen_tcp.accept(listen_socket) do
{:ok, socket} ->
spawn(__MODULE__, :handle_client, [socket])
accept_loop(listen_socket)
{:error, reason} ->
IO.puts("接受連接失敗: #{reason}")
end
end
def handle_client(socket) do
# 接收數據
case :gen_tcp.recv(socket, 0) do
{:ok, data} ->
IO.puts("收到: #{data}")
:gen_tcp.send(socket, "Echo: #{data}")
# 繼續接收
handle_client(socket)
{:error, :closed} ->
IO.puts("客戶端斷開連接")
{:error, reason} ->
IO.puts("接收數據失敗: #{reason}")
end
end
end

28
lib/tcp_proxy.ex Normal file
View File

@@ -0,0 +1,28 @@
defmodule TcpProxy do
use GenServer
def start_link({watch_pid, to_host, to_port}) do
GenServer.start_link(__MODULE__, {watch_pid, to_host, to_port})
end
def init({watch_pid, to_host, to_port}) do
{:ok, socket} =
:gen_tcp.connect(String.to_charlist(to_host), to_port, [:binary, active: true])
{:ok, {watch_pid, socket}}
end
def handle_info({:tcp, _socket, data}, {watch_pid, _socket} = state) do
send(watch_pid, {:send, data})
{:noreply, state}
end
def handle_info({:send, data}, {watch_pid, socket} = state) do
:gen_tcp.send(socket, data)
{:noreply, state}
end
def handle_info({:tcp_closed, _port}, state) do
{:stop, :normal, state}
end
end

35
lib/tcp_watcher.ex Normal file
View File

@@ -0,0 +1,35 @@
defmodule TcpWatcher do
use GenServer
def start_link({to_host, to_port, listen_socket}) do
GenServer.start_link(__MODULE__, {to_host, to_port, listen_socket})
end
def init({to_host, to_port, listen_socket}) do
{:ok, {to_host, to_port, listen_socket}, {:continue, :accept}}
end
def handle_continue(:accept, {to_host, to_port, listen_socket} = _state) do
{:ok, socket} = :gen_tcp.accept(listen_socket)
start_link({to_host, to_port, listen_socket})
{:ok, proxy_id} = TcpProxy.start_link({self(), to_host, to_port})
{:noreply, {to_host, to_port, listen_socket, socket, proxy_id}}
end
def handle_info({:tcp_closed, _socket}, state) do
{:stop, :normal, state}
end
def handle_info(
{:tcp, _socket, data},
{_to_host, _to_port, _listen_socket, _socket, proxy_id} = state
) do
send(proxy_id, {:send, data})
{:noreply, state}
end
def handle_info({:send, data}, {_to_host, _to_port, _listen_socket, socket, _proxy_id} = state) do
:gen_tcp.send(socket, data)
{:noreply, state}
end
end