えこーさーばー

無制限にプロセスを生成するので、お遊び程度で。
現実的には acceptor でブロックするのがスマートだと思われます。これは acceptor でブロックせずに別のプロセスにさくっと渡しています。

プロセスプールの監視等はたけまるさんやid:cooldaemonさんのこの辺りが詳しいです。

そのうち実装します ... 。

さーばー

-module(server).
-compile(export_all).

-define(kOptListen, [{active, false}, binary, {packet, 2}]).
-define(kMaxAcceptors, 5).

start() ->
  case gen_tcp:listen(5000, ?kOptListen) of
    {ok, ListenSocket} ->
      start_acceptors(?kMaxAcceptors, ListenSocket),
      {ok, Port} = inet:port(ListenSocket),
      Port;
    {error, _Reason} ->
      error
  end.

start_acceptors(0, _) ->
  ok;
start_acceptors(Num, ListenSocket) ->
  Pid = spawn(fun() -> acceptor(ListenSocket) end),
  io:format("acceptor: ~p:~p\n", [Num, Pid]),
  start_acceptors(Num-1, ListenSocket).

acceptor(ListenSocket) ->
  case gen_tcp:accept(ListenSocket) of
    {ok, Socket} ->
      {ok, Port} = inet:port(Socket),
      io:format("accept: ~p, ~p\n", [self(), Port]),
      Pid = spawn(fun() -> connect(Socket) end),
      gen_tcp:controlling_process(Socket, Pid),
      % connect(Socket)
      acceptor(ListenSocket);
    {error, _Reason} ->
      acceptor(ListenSocket)
  end.

connect(Socket) ->
  inet:setopts(Socket, [{active, once}]),
  receive
    {tcp, Socket, Packet} ->
      io:format("tcp: ~p\n", [Packet]),
      gen_tcp:send(Socket, Packet),
      connect(Socket);
    {tcp_closed, Socket} ->
      io:format("tcp_closed: ~p\n", [self()]),
      ok = gen_tcp:close(Socket);
    {tcp_error, Socket, _Reason} ->
      io:format("tcp_error: ~p\n", [self()]),
      ok = gen_tcp:close(Socket)
  end.

くらいあんと

-module(client).
-compile(export_all).

-define(kOptions, [{active,false}, binary, {packet,2}]).

client(Message) ->
  {ok, Sock} = gen_tcp:connect("localhost", 5000, ?kOptions),
  gen_tcp:send(Sock,Message),
  A = gen_tcp:recv(Sock, 0),
  gen_tcp:close(Sock),
  A.