我修改了this server以使用gen_tcp:recv
,以便將數據包的字節數限制爲50.我註釋掉了行inet:setopts(Socket, [{active, once}]),
,因爲gen_tcp:recv
應該是{active,false}
。這是客戶端ERL殼Erlang:gen_tcp:recv()沒有收到客戶端發來的數據包?
2> cp3:client().
exit
3>
,這是服務器端ERL殼
4> cp3:server().
Started Server:
<0.46.0>
Accept Server:
Pid <0.48.0>
Connection accepted
Accept Server:
Loop Server:
5>
我也想知道我怎麼能知道,如果插座與返回值關閉{tcp_closed, Socket}
如果gen_tcp:recv
不創建一個?
-module(cp3).
-export([client/0, server/0,start/0,accept/1,enter_loop/1,loop/1]).
client() ->
{ok, Socket} = gen_tcp:connect("localhost", 4001,[list, {packet, 0}]),
ok = gen_tcp:send(Socket, "packet"),
receive
{tcp,Socket,String} ->
io:format("Client received = ~p~n",[String]),
io:format("Client result = ~p~n",[String]),
gen_tcp:close(Socket)
after 1000 ->
exit
end.
server() ->
Pid = spawn(fun()-> start() end),
Pid.
start() ->
io:format("Started Server:~n"),
{ok, Socket} = gen_tcp:listen(4001, [binary, {packet, 0},{reuseaddr, true},{active, false}]),
accept(Socket).
accept(ListenSocket) ->
io:format("Accept Server:~n"),
case gen_tcp:accept(ListenSocket) of
{ok, Socket} ->
Pid = spawn(fun() ->
io:format("Connection accepted ~n", []),
enter_loop(Socket)
end),
io:format("Pid ~p~n",[Pid]),
gen_tcp:controlling_process(Socket, Pid),
Pid ! ack,
accept(ListenSocket);
Error ->
exit(Error)
end.
enter_loop(Socket) ->
%% make sure to acknowledge owner rights transmission finished
receive ack -> ok end,
loop(Socket).
loop(Socket) ->
%% set socket options to receive messages directly into itself
%%inet:setopts(Socket, [{active, once}]),
io:format("Loop Server:~n"),
case gen_tcp:recv(Socket, 50) of
{ok, Data} ->
case Data of
<<"packet">> ->
io:format("Server replying = ~p~n",[Data]),
gen_tcp:send(Socket, Data),
loop(Socket)
end;
{error, Reason} ->
io:format("Error on socket ~p reason: ~p~n", [Socket, Reason])
end.
對不起,我不太明白你的問題。在活動套接字中,當套接字關閉時,控制進程將發送'{tcp_closed,Socket}'消息,而對於被動套接字調用'gen_tcp:recv'將返回'{error,closed}'。 「*主動性*」是針對每一端設定的,可以是不同的。如果在Erlang之外的套接字的另一端是不相關的,它是如何處理的。 – rvirding 2013-03-25 11:48:38
好吧,我還有一個其他問題,這是一個並行服務器,它意味着它爲每個連接的客戶端產生一個新的進程? – pandoragami 2013-03-25 19:04:21
是的。函數'accept/1'位於遞歸循環中。它調用'gen_tcp:accept',當它返回一個新的數據套接字時,它會產生一個在該連接上運行'enter_loop/1'的新進程。然後,它轉交套接字的控制權,調用'gen_tcp:controlling_process/2',然後遞歸地自我調用以等待它產生新進程的新連接,等等。直到'gen_tcp:accept '返回一個錯誤,函數終止。這是爲每個連接創建新流程的常用方法。 – rvirding 2013-03-26 07:00:48