erlang 趣事之 socket通讯

来源:互联网 发布:淘宝上如何申请售后 编辑:程序博客网 时间:2024/06/05 02:06
现在看erlang的socket 编程,写了个demo,一直报错。为什么呢?经过指导说是我采用的短连接,没有及时关闭socket导致的。什么是短连接?什么是长连接?

长连接与短连接

所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持。 
短连接是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接。
比如http的,只是连接、请求、关闭,过程时间较短,服务器若是一段时间内没有收到请求即可关闭连接。 
其实长连接是相对于通常的短连接而说的,也就是长时间保持客户端与服务端的连接状态。

长连接与短连接的操作过程

 

通常的短连接操作步骤是: 
连接→数据传输→关闭连接;


而长连接通常就是: 
连接→数据传输→保持连接(心跳)→数据传输→保持连接(心跳)→……→关闭连接; 
这就要求长连接在没有数据通信时,定时发送数据包(心跳),以维持连接状态,短连接在没有数据传输时直接关闭就行了

什么时候用长连接,短连接?

长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。

下面上代码



server:

-module(server).%%% =================================================================%%% API functions%%% =================================================================-export([]).-compile(export_all).%%% =================================================================%%% Internal functions%%% =================================================================start_server()->TCPOptions = [binary, {packet, raw}, {active, false}, {reuseaddr, true}],    {ok, ListenSocket}=gen_tcp:listen(8848,TCPOptions),    accept(ListenSocket).    accept(ListenSocket)->    {ok,Socket} = gen_tcp:accept(ListenSocket),spawn(?MODULE, accept,[ListenSocket]),    process_request(Socket).    process_request(Socket)->    case gen_tcp:recv(Socket,0,5000) of        {ok,Binary}->            io:format("received request message ~p~n", [Binary]),            gen_tcp:send(Socket, "process successful"),gen_tcp:close(Socket);         %%process_request(Socket);         {error, closed}->            io:format("socket close ~n");        _Req->            io:format("receive ~p~n", [_Req])    end.</span>

client:

-module(client).%%% =================================================================%%% API functions%%% =================================================================-export([]).-compile(export_all).%%% =================================================================%%% Internal functions%%% =================================================================client() ->TCPOptions = [binary, {packet, raw}, {active, false}, {reuseaddr, true}],case gen_tcp:connect("localhost", 8848, TCPOptions, 5000) of{ok, Socket} ->ResData = send_and_recv(Socket, "test socket", 5000),gen_tcp:close(Socket),ResData;{error, Reason} ->throw(Reason)end.do_recv(Sock, Timeout, Bs) ->    case gen_tcp:recv(Sock, 0, Timeout) of        {ok, B} ->        do_recv(Sock, Timeout, [Bs, B]);        {error, closed} ->            {ok, list_to_binary(Bs)};        Error ->            Error    end.send_and_recv(Socket, ReqData, Timeout) ->    case gen_tcp:send(Socket, ReqData) of        ok ->            case do_recv(Socket, Timeout, []) of                {ok, ResData} ->                    ResData;                {error, timeout} ->                    gen_tcp:close(Socket),                    throw("Time out");                {error, Reason} ->                    gen_tcp:close(Socket),                    throw(Reason)            end;        {error, Reason} ->            gen_tcp:close(Socket),            throw(Reason)    end.


(我标记红色的那行do_recv(Sock, Timeout, [Bs, B]);) 这里client中不断取数据,但是server没close连接,就不会返回数据了,这种写法只适用服务端处理完立刻关闭socket的情况,即短连接。


下面是测试结果:

server端:

Eshell V7.0  (abort with ^G)(zhb@127.0.0.1)1> make:all().Recompile: src/serverup_to_date(zhb@127.0.0.1)2> server:start_server().received request message <<"test socket">>ok(zhb@127.0.0.1)3> 

client端:

Eshell V7.0  (abort with ^G)(zhb1@127.0.0.1)1> client:client().process successfulok(zhb1@127.0.0.1)2> 

菜鸟一枚,如果有不对的地方请指正!谢谢。

(今天库里28岁生日!)


1 0
原创粉丝点击