2013-03-25 42 views
4

我修改了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. 
+0

對不起,我不太明白你的問題。在活動套接字中,當套接字關閉時,控制進程將發送'{tcp_closed,Socket}'消息,而對於被動套接字調用'gen_tcp:recv'將返回'{error,closed}'。 「*主動性*」是針對每一端設定的,可以是不同的。如果在Erlang之外的套接字的另一端是不相關的,它是如何處理的。 – rvirding 2013-03-25 11:48:38

+0

好吧,我還有一個其他問題,這是一個並行服務器,它意味着它爲每個連接的客戶端產生一個新的進程? – pandoragami 2013-03-25 19:04:21

+0

是的。函數'accept/1'位於遞歸循環中。它調用'gen_tcp:accept',當它返回一個新的數據套接字時,它會產生一個在該連接上運行'enter_loop/1'的新進程。然後,它轉交套接字的控制權,調用'gen_tcp:controlling_process/2',然後遞歸地自我調用以等待它產生新進程的新連接,等等。直到'gen_tcp:accept '返回一個錯誤,函數終止。這是爲每個連接創建新流程的常用方法。 – rvirding 2013-03-26 07:00:48

回答

4

我不是很清楚你的問題,但上面的代碼不起作用。希望以下回答你的問題。您的tcp收到case gen_tcp:recv(Socket, 50) of有一個錯誤。它正在等待50個字節的讀取。檢查文檔gen_tcp:recv/2。更改長度(封隔器6的長度,但最好爲0)以接收所有字節。

該值不會限制數據的大小,但它不會將數據發送回來,直到它接收到長度爲50的數據爲止。您可能需要接受並檢查它。

+0

你是對的,那就是我所需要的,只是Erlangs的文檔被非常詳細的解釋了,我認爲任何超過'recv'設置的限制的數據包都會被丟棄,我沒有注意到沒有任何東西會被髮回給客戶。 – pandoragami 2013-03-25 18:32:56

相關問題