2010-12-01 13 views
2

私はErlangで携帯電話クライアントと通信するTCPサーバーを実装しています。 携帯電話はオフラインになるので、サーバーはそれを検出できる必要があります。 したがって、サーバーにタイムアウトを指定してクライアントにメッセージを送信し、タイムアウト が発生すると接続が閉じられ、クライアントがオフラインとマークされるようにします。erlangソケットの送信タイムアウトが発生しない

私は、これはサーバー上のオプションを聞く使用:私は、サーバーと携帯電話との間の接続をセットアップする

[{certfile, "cert.pem"}, 
{keyfile, "key.pem"}, 
{reuseaddr, true}, 
{active, false}, 
{send_timeout, 10000}] 

した後、私は(すべての無線信号をシャットダウンします)機内モードに電話を切り替えて、サーバー上でssl:sendを実行します。送信関数happlyyは、パケットが正常に送信されたかのようにokを返しました。

どうしたのですか?

+0

どこからsend_timeoutを取得しましたか? 'ssl'モジュールを見ると、そのオプションは表示されません。 – ZeissS

+0

彼はそれをinetから手に入れました。たとえば 'ssl:connect/4'を使用している場合、' inet'からのタイムアウトを含むソケットオプションを指定することができます。 –

答えて

2

ソケットの{send_timeout_close, true}パラメータをinetから設定しましたか?そうでなければ、ソケットは閉じず、タイムアウトエラーだけを返します。また、リスクsslはあなたのエラーを呑み込んで、何かをします。

他のいくつかのポイント:

  • がエラーの任意のssl:sendssl:receiveオプションの戻り値をチェックすることを忘れないでください。送信がうまくいったことを知ることは重要です。

    ok = ssl:send(Sock, Data), 
    
  • 根本的なTCP/IPスタックは、実際にも、send_timeoutセットでデータを受け入れるかもしれないが、他のエンドポイントがダウンしているとして、それを送信することはできません。クローズドポートの知識は、スタックがACKを受け取っていないことを認識すると、後で最初に到着します。

  • inetで定義されているソケットの入力タイプはrawです。 OS固有のソケットオプションを設定できます。接続の喪失を検出する際に、OSをより積極的に強制することは可能かもしれません。

  • もう1つの選択肢は、ssl:recv/3コールですべてをキューに入れることです。タイムアウトは、ソケットのステータスに関係なく、デバイスの損失を意味します。それは、決定された経路に沿って進行しないので、相手側のアプリケーション障害も検出するという利点がある。これ以上のリクエストを処理するには、これを行う必要があります。

  • 携帯電話クライアントも動作できます。 SSLを介してメッセージを送信し、受信が到着しない場合(飛行機モードのため)、何かが間違っていることがわかります。ただし、サーバーはこれを認識しないことがあります。

  • TCP/IPは、信頼性の高い接続指向のストリームプロトコルです。突然の切断を防ぐものではありません。これはあなたのプロトコルであるので、重要です。は、切断問題自体を処理する必要があります。プロトコルに何らかの確認や確認がある場合は特に重要です。

+0

それはおそらく問題です。私はsend_timeout_closeを設定しましたが、ssl:sendは常にokを返します。 ssl:sendはACKを待つのではなく、常に成功を返すシステムコールに依存しているようです。 –

関連する問題