Distribution by another means

Ulf Wiger <>
Tue Jun 13 18:09:35 CEST 2000

I'm just now building a network of cooperating web servers using
"HTTP-based RPC". That is, the web servers run Erlang, and when they
need to communicate, they use a set of predefined "internal requests"
via HTTP:

query_internal(Host, Port, What, Req) ->
    {ok, Sock} = gen_tcp:connect(Host, Port, [binary, {packet, 0}]),
    Auth = ccv_auth:internal_pack_user(Req#ccv_req.user),
    Query = ["/ccviewer/internal/", What],
    Cmd = ["GET ", Query, " HTTP/1.0\r\n"
           "Cookie: ", Auth, ";\r\n"
    ok=io:format("connected~n", []),
    gen_tcp:send(Sock, list_to_binary(Cmd)),

do_recv(Sock) ->
        {tcp, Sock, Data} ->
            ok=io:format("received ~p~n", [Data]),
            {B1,B2} = split_binary(Data, 4),
            LengthBytes = binary_to_list(B1),
            Length = i32(LengthBytes),
            ok=io:format("Length = ~p~n", [Length]),
            case size(B2) of
                L when L == Length ->
                    ok=io:format("Got whole packet~n", []),
                _ ->
                    ok=io:format("wait for more~n", []),
                    do_recv(Sock, Length, B2)
    after 10000 ->

do_recv(Sock, Length, Bin) ->
        {tcp, Sock, Data} ->
            Bin2 = list_to_binary([Bin, Data]),
            case size(Bin2) of
                Length ->
                    ok=io:format("Got whole packet~n", []),
                _ ->
                    ok=io:format("wait for more~n", []),
                    do_recv(Sock, Length, Bin2)
    after 10000 ->

i32([B1,B2,B3,B4]) ->
    ((B1 bsl 24) bor
     (B2 bsl 16) bor
     (B3 bsl 8) bor
i32(I) when integer(I) ->
    B1 = (I band 16#ff000000) bsr 24,
    B2 = (I band 16#00ff0000) bsr 16,
    B3 = (I band 16#0000ff00) bsr 8,
    B4 =  I band 16#000000ff,
    [B1, B2, B3, B4].

And the server side looks kinda like this:

ccv_handler({get, "/internal/" ++ Query, Args}, Socket, Env) ->
    X = {get, Query, Args},
    put(socket, Socket),
    Result = case ccv_auth:internal_request(X, Socket, Env) of
                 {'EXIT', Reason} ->
                     {error, Reason};
                 {ok, NewX, Req} ->
                     put(request, Req),
                     handle_internal_request(NewX, Req);
                 Other ->
    Bin = term_to_binary(Result),
    gen_tcp:send(Socket, [ccv_lib:i32(size(Bin)), Bin]);

Of course, one also needs an HTTP server. Personally, I use a
home-grown, based on Joe's/Luke's pico. A more natural choice perhaps
would be to use INETS, but what fun would that be?

At AXD301, we had a similar problem, and solved it there with CORBA.
It's also reasonably straightforward. I can dig up the code if you'd


On Tue, 13 Jun 2000, Francesco Cesarini wrote:

>Might seem far fetched, but when discussing this problem a few years
>ago, one of the simplest ideas and solutions which came to up was to run
>the calls through the WWW proxy, masking the http requests as arguments
>in the URL.
>Sean Hinde wrote:
>> I need to connect up two separate Erlang/OTP based systems which are
>> separated amongst other things by a firewall.
>> I don't want to run the standard distribution mechanism between the two
>> systems for various reasons but need a simple rpc type call in both
>> directions.
>> Out of all the mechanisms available in OTP what are peoples views on which
>> would be the quickest and easiest mechanism requiring least overhead and
>> minimum complexity. Full on CORBA would work but is probably overkill??
>> Views?
>> Sean

Ulf Wiger                                    tfn: +46  8 719 81 95
Network Architecture & Product Strategies    mob: +46 70 519 81 95
Ericsson Telecom AB,              Datacom Networks and IP Services
Varuvägen 9, Älvsjö,                    S-126 25 Stockholm, Sweden

More information about the erlang-questions mailing list