Skip to content

Instantly share code, notes, and snippets.

@zambal
Created December 12, 2013 13:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zambal/7927631 to your computer and use it in GitHub Desktop.
Save zambal/7927631 to your computer and use it in GitHub Desktop.
Minimalistic example that exposes unexpected file:sendfile/5 behaviour.
-module(sendfile).
%API
-export([server/0, clients/0]).
%Internal loops
-export([client/1, acceptor/2, loop/2]).
server() ->
{ok, Socket} = gen_tcp:listen(8008, [{ip, {127, 0, 0, 1}}, {active, false}]),
[spawn_link(?MODULE, acceptor, [Socket, N]) || N <- lists:seq(1, 10)],
ok.
clients() ->
[spawn_link(?MODULE, client, [N]) || N <- lists:seq(1, 50)],
ok.
acceptor(ListenSocket, N) ->
case gen_tcp:accept(ListenSocket, 60000) of
{ok, Socket} ->
?MODULE:loop(Socket, N),
?MODULE:acceptor(ListenSocket, N);
_ -> ok
end.
loop(Socket, N) ->
case receive_data(Socket) of
closed ->
ok;
Path ->
sendfile(Socket, Path),
io:format("acceptor~p has send a file.~n", [N]),
%timer:sleep(100),
?MODULE:loop(Socket, N)
end.
client(N) ->
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, 8008, [{active, false}]),
send_path(Socket),
case receive_data(Socket) of
closed ->
ok;
File ->
io:format("client~p has received ~p bytes.~n", [N, length(File)])
end,
gen_tcp:close(Socket).
receive_data(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
Data;
{error, closed} ->
closed;
Error ->
gen_tcp:close(Socket),
exit(Error)
end.
sendfile(Socket, Path) ->
{ok, Fd} = file:open(Path, [read, raw, binary]),
file:sendfile(Fd, Socket, 0, 0, []),
file:close(Fd).
sendfile2(Socket, Path) ->
{ok, File} = file:read_file(Path),
gen_tcp:send(Socket, File).
send_path(Socket) ->
gen_tcp:send(Socket, ?FILE).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment