Beginner: Unexplained network behavior

Sean Hinde <>
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