Beginner: Unexplained network behavior
Sean Hinde
sean.hinde@REDACTED
Mon Apr 26 23:10:27 CEST 2004
Hi,
On 23 Apr 2004, at 16:23, Aaron Hunter wrote:
> Hello,
>
> A long time Java developer I recently discovered Erlang and am very
> impressed. With a few improvements Erlang could very well be a J2EE
> killer.
Been there, done that (actually I need to be careful as our J2EE
replacing system is not live yet...)
>
> I wrote this simple module to explore how sockets work in Erlang but
> am puzzled by its behavior. It is supposed to scan 254 IP's
> simultaneously. looking for HTTP servers. Over the course of several
> runs, however, it gives me different answers and often misses HTTP
> servers.
>
> Can someone point out what I am doing wrong?
> Thank you.
A couple of things could be improved:
1. If you use spawn_link rather than spawn then you guarantee to get a
message of some sort from each spawned process, even if it crashes. If
you use proc_lib:spawn_link, and have the sasl application running then
you will also get nicely formatted crash reports if any process exits
abnormally.
2. The documentation :-(. gen_tcp:connect/2 can actually throw an
exception if it fails to connect rather than returning {error, Reason}.
The implementation from gen_tcp.erl is:
connect(Address, Port, Opts, Time) ->
Timer = inet:start_timer(Time),
Res = (catch connect1(Address,Port,Opts,Timer)),
inet:stop_timer(Timer),
case Res of
{ok,S} -> {ok,S};
{error, einval} -> exit(badarg);
{'EXIT',Reason} -> exit(Reason);
Error -> Error
end.
The combination of these two things means that you could get your
result.
The lesson for you is to use spawn_link anywhere you are spawning a
process to do some work where you always want an answer.
It is unfortunate in the light of your opening comments that you have
run into a documentation error so soon in your experimentation. I would
say that the documentation is generally pretty accurate, but still
could do with some work on return values here and there.
Best of luck with Erlang.
Regards,
Sean
>
> -module( scanner ).
> -export( [scan_http/1, scan_port/3] ).
>
> % Check for an open socket on the given port
> scan_port( PID, IP, Port ) ->
> case gen_tcp:connect( IP, Port, [], 5000) of
> { ok, Socket } ->
> gen_tcp:close( Socket ),
> PID ! { found, IP, Port };
> { error, _ } ->
> PID ! { none, IP }
> end.
>
> % Wait for all 254 processes to finish
> wait( 254, Found ) ->
> io:fwrite("~nFound ~B HTTP servers: ~p~n", [ length( Found ), Found
> ]);
> wait( Count, Found ) ->
> receive
> { found, IP, Port } ->
> io:fwrite("+"),
> wait( Count + 1, [{IP,Port}|Found] );
> { none, IP } ->
> io:fwrite("."),
> wait( Count + 1, Found )
> end.
>
> % Call with a network IP tuple in the form {192,168,0,0}
> scan_http( {A,B,C,D} ) ->
> io:fwrite("Scanning ~n"),
> lists:foreach( fun(Host) -> spawn( ?MODULE, scan_port, [ self(),
> {A,B,C,Host}, 80 ] ) end, lists:seq(1,254) ),
> wait( 0, [] ).
>
>
>
>
>
More information about the erlang-questions
mailing list