2012-05-10 35 views
2

これは、私が何をしても、パケットが一緒に押し込まれて相手を区別しなければならないためです(オブジェクトは簡単、可変文字列は痛みを伴う可能性があるため)。これを避ける方法はありますか?あなたは、2つの1回の後に起こる送信見ることができるようにここでTcpclient.NoDelay = trueの後でも、socket.sendはパケットを一緒に追加します。

は、私が働いているいくつかの粗コード(はい、初期化がここで起き、これが悪いのプログラミング規則についてとても残念ラフテストコードである)

sender.Connect("localhost", 8523); 
    sender.Client.SendTimeout = 1000; 
    sender.NoDelay = true; 
    byte[] buffer = ASCIIEncoding.ASCII.GetBytes(message); 
    sender.Client.Send(buffer); 
    buffer = ASCIIEncoding.ASCII.GetBytes("DISCONNECT"); 
    sender.Client.Send(buffer); 
    sender.Client.Close(); 

ですもう一方とソケットは、それらを一緒に送信することが最適であると判断します。それは素晴らしいですが、私はそれを望んでいません。したがって、もう一方の端に、それは

helloDISCONNECT 

なってしまう私は、彼らが自動的にブロッキングキューにロードされているように、2つの分離で受信する必要があると私は、オブジェクトのサイズや文字列解析に対処する必要はありません。

+1

あなたは、どのパケットに基づいてプログラミングするのではなく、全体をストリームのように扱うことを強くお勧めします。これは答えではありませんが、コメントの中の提案です(はい、これはあなたが何らかの解析をする必要があることを意味します)。 – payo

+0

別の提案は、あなたのためにこれらの詳細を包む図書館で、例えばWCF(http://msdn.microsoft.com/en-us/library/ms734712.aspx) – payo

+2

TCPは常にストリームであり、パケットベースのプロトコルではありません。 'NoDelay'は正確さには影響せず、パフォーマンスのみに影響します。 – CodesInChaos

答えて

1

あなたが期待する表示されます。

sender.NoDelay = true; 

は、本質的にすることを意味する:

sender.Client.Send(buffer); 

を...ビットは、あなたのNICオフされるまでブロッキング呼び出しします。残念ながら、これはそうではありません。 NoDelayは、ネットワーク層に待機を知らせませんが、Sendで行っている基本的な呼び出しには、いくつかの非同期動作があり、プログラムのスレッドは、2番目の文字列を追加する前にネットワーク層のスレッドが起動しないように、

続きを読むNoDelayhereを参照してください。そこには詳しい説明があります。関連する

いくつかの引用符:

はストリームソケット がNagleアルゴリズムを使用しているかどうかを指定するブール値を取得または設定します。

Nagleアルゴリズムを使用すると、ビットを約束することができた場合でも、小さなパケットをバッファリングして、ほかに特定の状況下で 1つのパケットに

をそれらを結合して送信するために ソケットを引き起こすことによって、ネットワークトラフィックを削減するように設計されて残すために、クライアントのネットワーク層は、クライアントコードが2つの「パケット」があることを見る機会を得る前に、それらをバッファリングすることがあります。

0

あなたが言及した制約でTCP上で個別にメッセージを受信したい場合は、各メッセージの後に接続をシャットダウンする必要があります。返信を期待していない場合は、読み取りと書き込みの両方をシャットダウンできます。応答が必要な場合は、書き込みのみのためにシャットダウンしてください。書き込みのためのシャットダウンを行うと、受信者は0バイトを受信し、受信者はメッセージの終わりを検出できます。たとえば、httpは次のように動作します。

ここでは、オーバーヘッドの原因となる各メッセージに対して新しいTCP接続を開く必要があります。しかし、多くのアプリケーションでは、これは問題ではありません。

免責事項:これはBSDソケットAPIを使用して簡単に実装できます。私はC#での経験はほとんどなく、これらの低レベルのソケット操作を実行するのに適したAPIを提供しているかどうかはわかりません。

2

TCPは受信者にバイトストリームを提示します。

ストリームがクローズされるまで、TCPソケットの各読み取りは、指定したバッファのサイズと1の間で返されます。それに応じてコードを書く必要があります。

TCPは、プログラムのメッセージフレーミングの概念を知らない、または気にしません。 3つの "メッセージ"を別々に送信して送信することは気にしません。有効なTCP実装では、ストリームから読み取る関数への呼び出しごとに1バイトを返すことができます。また、バイトを返す前にバッファリングすることもできます。それに応じてコードを書く必要があります。

TCPで送信するときにメッセージを処理する場合は、独自のフレーミングを適用する必要があります。メッセージを読むときは、自分自身でフレームを処理する必要があります。これは一般に、既知のサイズの長さプレフィックスまたはメッセージターミネータのいずれかを意味します。

私はこれをより詳細にはhereと扱いますが、コードはC++でありますが、コンセプトはそのまま適用されます。

1

sender.NoDelay = trueに加えて、確かに私のために働くトリックは、sender.Client.Send(...)の後に追加の遅延を使用したものです。Thread.Sleep(50)の形式です。

実際の番号は調査されていませんでした。私は送信キューにバックログを作成せずに待機するのに妥当な時間として50msをゲストにしました。動作環境。

救済:私のデータを受信するアプリケーションは、各TCPパケットが画面上の異なる行になるように、ビデオにテキストを重ねることができるCCTVレコーダーです。私はNagleのアルゴリズムについて何かすることを余儀なくされました。さもなければ、私の "行"は一緒に集められていました。(マシンのバッファ使用と明らかに関係していた追加のアーティファクトはもちろんですが)

+0

この "解決策"の後で、コードを変更して、行の長さにパッドを埋め込んだコードを送信しました(40文字のようなものでした)。この変更により、回避策が廃止されました。 – Doc

関連する問題