2

I have .NET TCP Sender sending to an Erlang receiver. The .NET component likes to use the IPv6 address ::1 when resolving localhost. I'm not quite sure how to get Erlang to listen on the IPv6 address using gen_tcp. Here's my attempt. Am I telling the wrong socket to do the listening? Thanks!

listen(Config) ->
    PortString = Config#cfg.eventbusport,
    GoodPort = check_int(PortString),
    Port = if GoodPort -> 
               list_to_integer(PortString);
           true ->
               ?DEFAULT_PORT
           end,                      %% IPv6 here --->
    {ok, XSocket} = gen_tcp:listen(Port, [binary, {packet, line}, {active, false}, {reuseaddr, true}, inet6, {ip, {0,0,0,0,0,0,0,1}}])
    end,
    accept(XSocket, Config).

accept(LSocket, Config) ->
    case gen_tcp:accept(LSocket) of
        {ok, Socket} ->
            spawn_link(fun() -> loop(Socket, Config) end),
            accept(LSocket, Config);
        {error, closed} ->
            logger("Accept: Closed socket.",[],1),
            listen(Config)
    end.

loop(Socket, Config) ->
    case inet:setopts(Socket, [{recbuf, 64000}]) of
        ok ->
            case gen_tcp:recv(Socket, 0) of
                {ok, Data} ->
                    SplitData = binary:split(Data,?CRLF,[global]),
                    discrim(SplitData, Config),
                    loop(Socket, Config);
                {error, closed} ->
                    logger("Loop: Closed socket.",[],1),
                    ok
            end;
        {error, Reason} ->
            logger("ERROR: Couldn't set the recbuf to 64k! Because ~p",[Reason],1)
    end.
batman
  • 1,447
  • 5
  • 16
  • 27
  • 1
    What is the problem exactly here? You get error messages or timeout or what? – dijxtra Nov 24 '11 at 09:18
  • *Update*: The issue I'm having is that I never get a connection. My C# sender cannot connect and therefore doesn't send data. It says that nothing is listening on the Address ::1 for the port 1971. – batman Nov 27 '11 at 18:58

1 Answers1

1

What is the actual problem you are having?

You should probably set the controlling process of the socket to the process you spawn to use the connection. So in your accept/2 you would do something like:

accept(LSocket, Config) ->
    case gen_tcp:accept(LSocket) of
        {ok, Socket} ->
            Pid = spawn_link(fun() -> loop(Socket, Config) end),
            gen_tcp:controlling_process(Socket, Pid),
            accept(LSocket, Config);
...

Another way of writing the accept loop is too spawn new accept loops instead. You get something like:

accept_loop(LSocket, Config) ->
    {ok,Socket} = gen_tcp:accept(LSocket),
    spawn_link(fun() -> accept_loop(LSocket, Config) end),
    loop(Socket, Config).

This without the error handling. You can pass the listen socket to other processes without problems. Of course, if the process which opened the listen socket dies then the socket is closed.

rvirding
  • 20,848
  • 2
  • 37
  • 56
  • Haven't found a need to set the controlling process, because if a socket closes after it's accepted it usually closes at the receiving loop, (at least in this design), but I might as well change anyway. See my comment on original question. – batman Nov 27 '11 at 19:13