2012-08-30 58 views
1

我正在實施一個gen_server,它的行爲與ssl認證服務器的接口一樣。如果收到的數據包錯誤(例如用戶名和密碼錯誤),ssl服務器會斷開連接。連接必須持久。如何確保使用SSL發送消息

以我gen_server,我打開與handle_cast/2向服務器的SSL連接:

handle_cast(connect, State) -> 
    ...... 
    case ssl:connect(Address, Port, Options, Timeout) of 
     {ok, NewSocket} -> 
      {noreply, State#state{socket=NewSocket}}; 
     {error, Reason} -> 
      gen_server:cast(?SERVER, connect), 
      {noreply, State#state{socket=undefined}}; 

,然後我等,其可以例如使用被髮送在handle_cast/2以外的其他消息:

gen_server:cast(Pid, {authenticate, User, Password}). 

每當收到這樣的鑄造消息我生成一個新的功能,其使用gen_server從服務器狀態恢復SSL套接字:呼叫/ 3,併發送認證消息給SSL服務器。如果發送部分返回一個錯誤,我嘗試重新連接,否則我在套接字上讀了一段時間,以確保套接字不會關閉,如果它重新連接。

send_auth(_, _, 0) -> 
    {error, max_num_reached}; 

send_auth(User, Password, Num) -> 
    Socket = gen_server:call(?SERVER, socket), 
    %% also a check that socket is not 'undefined' 
    case ssl:send(Socket, AuthMessage) of 
     ok -> 
      case ssl:recv(Socket, 0, 2000) of 
      {error, timeout} -> 
       ok; 
      _ -> 
       gen_server:cast(?SERVER, connect), 
       send_auth(User, Password, Num-1) 
      end, 
     {error, closed} -> 
      gen_server:cast(?SERVER, connect), 
      send_auth(User, Password, Num-1) 
    end. 

我做了很多測試,但每一次,如果消息(不是最後一個)是錯誤的,沒有下面的消息是實際交付。

我該如何授予所有有效的認證信息傳遞到認證服務器?此外,如何確保服務器僅在尚未嘗試連接的情況下才能連接?否則,這就像DOS攻擊!

回答

0
  1. 我可以理解,只有一個認證服務器系統,爲什麼你不能連接到正確的gen_server的init?如果連接有點可靠,如果連接有任何問題,並且讓主管重新啓動它,則可以殺死gen_server。這可能會解決你的DOS問題。
  2. 當你用產生額外的進程send_auth你可以通過參數傳遞套接字連接,而不是執行gen_server調用。
  3. 爲了保證交付,您將在協議中添加某種確認。 Auth服務器應回覆send_auth,並確認它已得到它。並且send_auth應該重試,直到它收到該確認或有一些其他回退行爲,以防永遠不會。