转载自 http://www.qingliangcn.com/?s=%E7%B2%98%E5%8C%85
recv(ClientSock, PacketLenOld, Remain)
when is_integer(PacketLenOld) and is_binary(Remain) ->
case gen_tcp:recv(ClientSock, 0) of
{ok, B} ->
Bin = <<Remain/binary, B/binary>>,
%% read the packet length
if PacketLenOld =:= 0 andalso erlang:byte_size(Bin) > 2
-> <<PacketLen:16, Remain2/binary>> = Bin;
true -> Remain2 = Bin, PacketLen = PacketLenOld
end,
?DEBUG("packet length ~p", [PacketLen]),
if
erlang:byte_size(Remain2) >= PacketLen
-> {RealData, Next} = split_binary(Remain2, PacketLen),
MainData = decode(RealData),
{ok, MainData, 0, Next};
true -> {continue, PacketLen, Remain2}
end;
{error, closed} ->
?DEBUG("socket closed ~p ~n", [ClientSock]),
{error, closed};
{error, Reason} ->
?ERROR_MSG("socket closed ~p with reason: ~p ~n", [ClientSock, Reason]),
{error, Reason}
end.
翻了翻文档发现实际上在erlang中没有必要这样麻烦
The Length argument is only meaningful when the socket is in
raw mode and denotes the number of bytes to read.
If Length = 0, all available bytes are returned.
If Length > 0, exactly Length bytes are returned, or an error;
recv(ClientSock) ->
case gen_tcp:recv(ClientSock, 2) of
{ok, PacketLenBin} -> <<PacketLen:16>> = PacketLenBin,
case gen_tcp:recv(ClientSock, PacketLen) of
{ok, RealData} ->
?DEBUG("recv data ~p", [RealData]),
{ok, decode(RealData)};
{error, Reason} ->
?ERROR_MSG("read packet data failed with reason: ~p", [Reason]),
{error, Reason}
end;
{error, Reason} ->
?ERROR_MSG("read packet length failed with reason: ~p", [Reason]),
{error, Reason}
end.
<!--EndFragment-->