长连接与短连接
所谓长连接,指在一个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岁生日!)