erlang 趣事之 socket通讯

现在看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/server
up_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岁生日!)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值