Skip to content

Instantly share code, notes, and snippets.

@xiaohanyu
Created August 13, 2017 11:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save xiaohanyu/7dca97d549b0934ce9fc137c628f6703 to your computer and use it in GitHub Desktop.
Save xiaohanyu/7dca97d549b0934ce9fc137c628f6703 to your computer and use it in GitHub Desktop.
Socket programming examples in erlang.
%% socket examples from Joe Armstrong's "Programming Erlang, Second Edition".
-module(socket_examples).
-compile(export_all).
-import(lists, [reverse/1]).
string2value(Str) ->
{ok, Tokens, _} = erl_scan:string(Str ++ "."),
{ok, Exprs} = erl_parse:parse_exprs(Tokens),
Bindings = erl_eval:new_bindings(),
{value, Value, _} = erl_eval:exprs(Exprs, Bindings),
Value.
nano_get_url() ->
nano_get_url("github.com").
nano_get_url(Host) ->
{ok, Socket} = gen_tcp:connect(Host, 80, [binary, {packet, 0}]),
ok = gen_tcp:send(Socket, "GET / HTTP/1.0\r\n\r\n"),
receive_data(Socket, []).
receive_data(Socket, SoFar) ->
io:format("~p~n", [SoFar]),
receive
{tcp, Socket, Bin} ->
receive_data(Socket, [Bin|SoFar]);
{tcp_closed, Socket} ->
list_to_binary(reverse(SoFar))
end.
start_nano_server() ->
{ok, Listen} = gen_tcp:listen(2345, [binary, {packet, 4},
{reuseaddr, true},
{active, true}]),
{ok, Socket} = gen_tcp:accept(Listen),
gen_tcp:close(Listen),
loop(Socket).
start_seq_server() ->
{ok, Listen} = gen_tcp:listen(2345, [binary, {packet, 4},
{reuseaddr, true},
{active, true}]),
seq_loop(Listen).
seq_loop(Listen) ->
{ok, Socket} = gen_tcp:accept(Listen),
loop(Socket),
seq_loop(Listen).
start_parallel_server() ->
{ok, Listen} = gen_tcp:listen(2345, [binary, {packet, 4},
{reuseaddr, true},
{active, true}]),
spawn(fun() -> par_connect(Listen) end).
par_connect(Listen) ->
{ok, Socket} = gen_tcp:accept(Listen),
spawn(fun() -> par_connect(Listen) end),
loop(Socket).
loop(Socket) ->
receive
{tcp, Socket, Bin} ->
io:format("Server received binary =~p~n", [Bin]),
Str = binary_to_term(Bin),
io:format("Server (unpacked) ~p~n", [Str]),
Reply = string2value(Str),
io:format("Server replying = ~p~n", [Reply]),
gen_tcp:send(Socket, term_to_binary(Reply)),
loop(Socket);
{tcp_closed, Socket} ->
io:format("Server socket closed~n")
end.
nano_client_eval(Str) ->
{ok, Socket} =
gen_tcp:connect("localhost", 2345,
[binary, {packet, 4}]),
ok = gen_tcp:send(Socket, term_to_binary(Str)),
receive
{tcp, Socket, Bin} ->
io:format("Client received binary = ~p~n", [Bin]),
Val = binary_to_term(Bin),
io:format("Client result = ~p~n", [Val]),
gen_tcp:close(Socket)
end.
error_test() ->
spawn(fun() -> error_test_server() end),
sleep(2000),
{ok, Socket} = gen_tcp:connect("localhost", 4321, [binary, {packet, 2}]),
io:format("connected to: ~p~n", [Socket]),
gen_tcp:send(Socket, <<"123">>),
receive
Any -> io:format("Any = ~p~n", [Any])
end.
error_test_server() ->
{ok, Listen} = gen_tcp:listen(4321, [binary, {packet, 2}]),
{ok, Socket} = gen_tcp:accept(Listen),
error_test_server_loop(Socket).
error_test_server_loop(Socket) ->
receive
{tcp, Socket, Data} ->
io:format("received:~p~n", [Data]),
_ = atom_to_list(Data),
error_test_server_loop(Socket)
end.
sleep(T) ->
receive
after T ->
true
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment