Erlang中的本地Pid/Socket和远程Pid/Socket

转载请注明,来自:http://blog.csdn.net/skyman_2001

Erlang中的Pid/Socket有本地和远程之分,它们之间的区别是什么?

对Pid来说,是<A.B.C>格式,其中A为0表示本地节点,为其他值表示远程节点(值为该远程节点在dist_entry中的内部索引);B为4字节无符号整数,代表的是进程id(index,范围是0~MAXPROCS,这里MAXPROCS等于32767);C为4个字节,为Serial(当B达到MAXPROCS时,C就增加)。

对Socket来说,是#Port<A.B>,其中A和Pid中的A一样,为0表示本地Socket,为其他值表示远程Socket;B为Socket index。

当Pid/Socket在进程间传送时,如果是跨节点,Erlang会自动把传过来的本地Pid/Socket转换成远程Pid/Socket。

那能不能直接使用远程Pid/Socket呢?经过我的测试,得出的结论是:Pid能;Socket不能。下面是测试的代码:

1. tcp_server.erl(注:这个是根据http://blog.163.com/myerlang@126/blog/static/16454075820105288592327/的代码稍微改写了一下)

-module(tcp_server).

-export([nano_client_eval/1, start_nano_server/1]).

nano_client_eval(Str) ->
    {ok,Socket}=gen_tcp:connect("localhost",2345,[binary,{packet,4}]),
	io:format("=== client socket: ~p~n", [Socket]),
    ok=gen_tcp:send(Socket,term_to_binary(Str)),
    loop1(Socket).

loop1(Socket) ->
    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)
	    loop1(Socket);
	_ ->
	    skip
    end.

start_nano_server(Pid) ->
    {ok,Listen}=gen_tcp:listen(2345,[binary,{packet,4},
                                            {reuseaddr,true},
                                            {active,true}]),
    {ok,Socket}=gen_tcp:accept(Listen),
	io:format("=== socket: ~p~n", [Socket]),
    gen_tcp:close(Listen),
	gen_tcp:send(Socket,term_to_binary("test local socket")),
    Pid ! {sock, Socket},
    loop2(Socket).

loop2(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]),
            gen_tcp:send(Socket,term_to_binary(Str)),
	    	gen_tcp:send(Socket,term_to_binary("one more msg")),
            loop2(Socket);
        {tcp_closed,Socket} ->
            io:format("Server socket closed~n")
    end.

2. msg_test.erl

-module(msg_test).
-export([loop/0, send/1]).

loop() ->
	receive
		{start_server, From} ->
			io:format("---start_server,from:~p~n", [From]),
			tcp_server:start_nano_server(From);
		{msg, D} ->
			io:format("---~p~n", [D]),
			loop();
		_Other ->
			loop()
	end.

send(Pid) ->
	Pid ! {start_server, self()},
	receive
		{sock, Socket} ->
			io:format("---sock: ~p~n", [Socket]),
			io:format("---send remote socket: ~n"),
			Res = gen_tcp:send(Socket,term_to_binary("test remote socket")),
			io:format("---Result: ~p~n", [Res]);
		_Other ->
			error
	end.
	

运行测试截图:


 

上图中红圈旁的序号表示操作的先后步骤。

由测试结果可以得出最终结论:
1. 直接用远程Pid向这个进程发消息是可以的,形如:Remote_pid ! Msg,就能把Msg消息发送到其他节点的这个进程上;

2. 用gen_tcp:send(Remote_socket, Bin)向该Socket发数据是不行的,会返回{error, closed}错误;而gen_tcp:send(Local_socket, Bin)则是可以的,客户端会成功收到数据(见上图中的蓝色方框内容)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值