2016-04-25 28 views
1

現在、2つの明確な使用例があるWebアプリケーションをビルドしています。WebSocketでのエラー処理の設計

  1. サーバーからの従来のクライアント要求データ。
  2. クライアントは、サーバーがクライアントにデータをプッシュした後に、サーバーからストリームを要求します。

現在、jsonメッセージをwebsocket経由で使用して1と2の両方を実装しています。しかし、クライアントが応答を待っているわけではないので、多くのエラー処理を手作業で行う必要があるため、これは難しいことが分かりました。それはちょうどいつか返事を得ることを望むメッセージを送るだけです。 Jsを使用してフロントエンドで反応し、バックエンドでClojureに反応します。

私はこれに関して2つの質問があります。

  1. 現在の設計では、WebSocketでのエラー処理の代替手段はありますか?
  2. UC1の残りの部分とUC2のWebソケットを使用して2つのUCを分割すると、残りの呼び出しのためにフロントエンドにfetchのようなものを使用することができます。

更新。 現在の問題は、WebSocket経由で非同期送信機能を構築する方法を知らないと、送信メッセージと応答メッセージと一致する可能性があります。

+1

webSocketメッセージングアーキテクチャで要求/応答を構築することは自明ではありません。当然、要求/応答ではありません。おそらく、各メッセージとレスポンスにある種のメッセージIDを使用してそれを行う必要があります。そのため、メッセージを送信するときに、そのメッセージに属している応答がそれぞれのIDに含まれていることがわかります。 – jfriend00

+0

残りの部分とウェブソケットを並べて使うのは簡単でしょうか? – user3139545

+0

まあ、httpは自然なリクエスト/レスポンスなので、使いやすいです。しかし、それはあなたがしようとしている場合は、サーバーからクライアントへのHTTPで要求/応答を行うことはできません。クライアントからサーバーへのリクエストがある場合は、HTTPとRESTのほうが簡単です。 – jfriend00

答えて

1

ここでは、socket.ioに対する要求/応答を行うための仕組みがあります。あなたは普通のwebSocketよりもこれを行うことができますが、インフラストラクチャを自分でもう少し構築する必要があります。これと同じライブラリには、クライアントとサーバーで使用することができます

function initRequestResponseSocket(socket, requestHandler) { 
    var cntr = 0; 
    var openResponses = {}; 

    // send a request 
    socket.sendRequestResponse = function(data, fn) { 
     // put this data in a wrapper object that contains the request id 
     // save the callback function for this id 
     var id = cntr++; 
     openResponses[id] = fn; 
     socket.emit('requestMsg', {id: id, data: data}); 
    } 

    // process a response message that comes back from a request 
    socket.on('responseMsg', function(wrapper) { 
     var id = wrapper.id, fn; 
     if (typeof id === "number" && typeof openResponses[id] === "function") { 
      fn = openResponses[id]; 
      delete openResponses[id]; 
      fn(wrapper.data); 
     } 
    }); 

    // process a requestMsg 
    socket.on('requestMsg', function(wrapper) { 
     if (requestHandler && wrapper.id) { 
      requestHandler(wrapper.data, function(responseToSend) { 
       socket.emit('responseMsg', {id: wrapper.id, data; responseToSend}); 
      }); 
     } 
    }); 
} 

これは、一意のID値が含まれているラッパーオブジェクトに送られたすべてのメッセージをラップすることによって動作します。次に、相手側が応答を送信すると、同じid値が含まれます。そのid値は、特定のメッセージの特定のコールバック応答ハンドラと一致させることができます。クライアントからサーバー、またはサーバーからクライアントへの両方の方法で動作します。

これを使用するには、両端のsocket.ioソケット接続でinitRequestResponseSocket(socket, requestHandler)を一度呼び出します。要求を受け取る場合は、要求があるたびに呼び出されるrequestHandler関数を渡します。要求を送信して応答を受け取るだけの場合は、接続の最後にrequestHandlerを渡す必要はありません。

メッセージを送信し、応答を待つ、あなたがこれを行う:については

initRequestResponseSocket(socket, function(data, respondCallback) { 
    // process the data here 

    // send response 
    respondCallback(null, yourResponseData); 
}); 

:あなたが要求を受信し、応答を返送している場合

socket.sendRequestResponse(data, function(err, response) { 
    if (!err) { 
     // response is here 
    } 
}); 

を、あなたはこれを行いますエラー処理を行うと、接続が失われたかどうかを監視できます。このコードにタイムアウトを設定すると、応答が一定時間内に到着しないとエラーが戻ってくることがあります。

ここではいくつかの時間内に来ない応答のタイムアウトを実装して、上記のコードの拡張バージョンです:

function initRequestResponseSocket(socket, requestHandler, timeout) { 
    var cntr = 0; 
    var openResponses = {}; 

    // send a request 
    socket.sendRequestResponse = function(data, fn) { 
     // put this data in a wrapper object that contains the request id 
     // save the callback function for this id 
     var id = cntr++; 
     openResponses[id] = {fn: fn}; 
     socket.emit('requestMsg', {id: id, data: data}); 
     if (timeout) { 
      openResponses[id].timer = setTimeout(function() { 
       delete openResponses[id]; 
       if (fn) { 
        fn("timeout"); 
       } 
      }, timeout); 
     } 
    } 

    // process a response message that comes back from a request 
    socket.on('responseMsg', function(wrapper) { 
     var id = wrapper.id, requestInfo; 
     if (typeof id === "number" && typeof openResponse[id] === "object") { 
      requestInfo = openResponses[id]; 
      delete openResponses[id]; 
      if (requestInfo) { 
       if (requestInfo.timer) { 
        clearTimeout(requestInfo.timer); 
       } 
       if (requestInfo.fn) { 
        requestInfo.fn(null, wrapper.data); 
       } 
      } 
     } 
    }); 

    // process a requestMsg 
    socket.on('requestMsg', function(wrapper) { 
     if (requestHandler && wrapper.id) { 
      requestHandler(wrapper.data, function(responseToSend) { 
       socket.emit('responseMsg', {id: wrapper.id, data; responseToSend}); 
      }); 

     } 
    }); 
} 
0

は面白い物事のカップルは、私は、あなたの質問や、あなたのデザインにあります実装の詳細を無視し、高レベルのアーキテクチャを見てみることをお勧めします。

あなたは、データとデータのいくつかのストリームで応答サーバに要求し、クライアントに見ていると述べています。ここで注意すべき二つのこと:

  1. HTTP 1.1は、ストリーミング応答(チャンク転送エンコーディング)を送信するオプションがあります。あなたのユースケースがストリーミングレスポンスの送信のみである場合、これはあなたに適しているかもしれません。たとえば、次の場合は保持されません。何らかの種類の要求に応答していないメッセージをクライアントにプッシュしたい(というサーバー側のイベント)。
  2. HTTPとは異なり、Webソケットは何らかの種類の要求 - 応答サイクルをネイティブに実装しません。独自のメカニズムを実装することで、プロトコルをそのまま使用することができます。サブプロトコルWAMPを行っています。

独自のメカニズムを実装することには、HTTPに明確な利点がある落とし穴があります。あなたの質問に記載された要件を与えられた私は、独自の要求/応答メカニズムを実装するのではなく、HTTPストリーミング方法を選択します。

+0

サーバーは要求なしでクライアントにメッセージをプッシュします。だから私は残りの部分を使用することを検討しているか、応答ロジックを送信して実装するだけです。 – user3139545

関連する問題