0

I have the following code using a gen_tcp socket, which should receive using {active, true} some binary commands that are always of size 5 (e.g. Command = <<"hello">>)

{ok, ListenSocket} = gen_tcp:listen(5555,  [{active, true}, {mode, binary}, 
                                            {packet, 0}]),
{ok, Socket} = gen_tcp:accept(ListenSocket),    
loop().

receive() ->
    {tcp, _Socket, Message:4/binary} ->
         io:format("Success~n", []),
         loop();
    {tcp, _Socket, Other} ->
         io:format("Received: ~p~n", [Other]),
         loop()
end.

But if I try to connect as a client like this:

1> {ok, S} = gen_tcp:connect("localhost", 5555, []).
   {ok,#Port<0.582>}
2> gen_tcp:send(S, <<"hello">>).
ok

I have in the receiving part:

Received: {tcp,#Port<0.585>,<<"hello">>}

so I suppose my error is in the pattern matching...but where?

user601836
  • 3,215
  • 4
  • 38
  • 48

2 Answers2

2

Your receive clause doesn't look right, it should be:

{tcp, _Socket, <<Message:5/binary>>} ->
  ....
johlo
  • 5,422
  • 1
  • 18
  • 32
  • for the future, if i change to ssl will <> still be good? just asking :) – user601836 Aug 27 '12 at 13:33
  • The protocol atom will be `ssl` instead of `tcp`, apart from that you should be fine – johlo Aug 27 '12 at 14:00
  • 2
    This code will work in 99%. But as you know TCP is stream protocol and it does not guarantee that your command will not be splitted in two or more packets or will not be joined with previous command. – asvyazin Sep 07 '12 at 03:52
0

As far as I understood you need gen_tcp:recv function. From documentation:

recv(Socket, Length) -> {ok, Packet} | {error, Reason}

In your code it will be something like:

...
{ok, Socket} = gen_tcp:accept(ListenSocket),
loop(Socket).

loop(Socket) -> 
    case gen_tcp:recv(Socket, 5) of
        {ok, Data} ->
            io:format("Success~n", []),
            loop(Socket);
        {error, closed} -> 
            ok
end.
Alexey Kachayev
  • 6,106
  • 27
  • 24
  • Yeah i know that option, but isn't it possible to use standard receive instead? I would rather prefer to handle it in that way. – user601836 Aug 27 '12 at 10:01
  • `receive` is not standard way to receive data from TCP socket (this is generic interface for working with `spawned` processes). What benefits will you get? – Alexey Kachayev Aug 27 '12 at 10:22
  • AFAIK gen_tcp:recv/2 is blocking. Moreover in a future implementation i will handle packets with {active, once} in handle_info of a gen_server behaviour – user601836 Aug 27 '12 at 10:42
  • Why blocking is a problem? Just replace `loop(Socket)` to `spawn(fun() -> loop(Socket) end)` – Alexey Kachayev Aug 27 '12 at 10:46