0

だから私はこのリアルタイムゲームを持っています。SFMLライブラリを使用してnagleを無効にしたC++サーバーと、asyncsocketを使用したクライアントもnagleを無効にします。1秒ごとに30パケットを送信しています。クライアントからサーバーへの送信に問題はありませんが、サーバーからクライアントへの送信時に、一部のパケットが移行しています。たとえば、「a」と「b」を完全に異なるパケットで送信している場合、クライアントはそれを「ab」として読み取ります。それは一度だけ起こりますが、それはゲームで本当の問題を引き起こします。

だから私は何をすべきですか?どうすればそれを解決できますか?多分それはサーバーの何かですか?たぶんOSの設定?

明確にするために:私はnagleを使用していませんが、まだこの問題があります。クライアントとサーバーの両方で無効にしました。

4

2 に答える 2

3

たとえば、「a」と「b」をまったく異なるパケットで送信すると、クライアントはそれを「ab」と読み取ります。それは一度だけ起こりますが、それはゲームで本当の問題を引き起こします.

あなたは TCP の基本的な性質を見失っていると思います。TCP はストリーム プロトコルであり、パケット プロトコルではありません。TCP は、送信者のデータ境界を尊重も保持もしません。別の言い方をすれば、TCP は送信した「パケット」を自由に結合 (または分割!) し、受信側で任意の方法で提示できます。TCP が尊重する唯一の制限は次のとおりです。バイトが配信される場合、送信されたのと同じ順序で配信されます。(そして、Nagle についてこれを変更するものは何もありません。)

したがって、サーバー上でsend(またはwrite) を 2 回呼び出すと、次の 6 バイトが送信されます。

"packet" 1: A B C
"packet" 2: D E F

クライアント側は、次のバイト シーケンスのいずれかrecv(または) である可能性があります。read

ABC / DEF
ABCDEF
AB / CD / EF

あなたのアプリケーションが送信者の 間の境界の知識を必要とする場合、writeその情報を保存して送信するのはあなたの責任です。

他の人が言ったように、それについては多くの方法があります。たとえば、情報の各量の後に改行を送信できます。これは (部分的に) HTTP、FTP、SMTP がどのように機能するかです。

データとともにパケット長を送信できます。これの一般化された形式は、「タイプ、長さ、値」の TLV と呼ばれます。固定長タイプ フィールド、固定長フィールド、および任意長の値を送信します。このようにして、値全体を読み取り、次の TLV の準備が整ったことがわかります。

送信するすべてのパケットの長さが同じになるように調整できます。

他にも解決策はあると思いますので、ご自身で考えていただければと思います。しかし、最初にこれを認識しなければなりません: TCP は、アプリケーション パケットマージまたは分割することができます。バイトの配信順序は信頼できますが、他には何もありません。

于 2011-07-07T17:24:33.637 に答える
1

両方のピアでNagleを無効にする必要があります。のようなレコードベースの別のプロトコルを見つけたい場合がありますSCTP

EDIT2

あなたはプロトコルを求めているので、これが私がそれをする方法です:

  • メッセージのヘッダーを定義します。32ビットヘッダーを選択するとします。

    Header:
        MSG Length: 16b
        Version: 8b
        Type: 8b
    
  • 次に、MSG Lengthバイトを含む実際のメッセージが届きます。

フォーマットができたので、どのように処理しますか?

サーバ

メッセージを書くときは、制御情報(実際には長さが最も重要です)を付加して、すべてを送信します。NODELAYを有効にするかどうかは、違いはありません。

クライアント

私はサーバーから継続的にものを受け取りますよね?だから私はある種のことをしなければなりませんread

  • サーバーからバイトを読み取ります。任意の金額が到着できます。少なくとも4バイトになるまで読み続けてください。
  • これらの4バイトを取得したら、それらをヘッダーとして解釈し、MSG Length
  • 少なくともMSG Lengthバイトが得られるまで読み続けてください。これでメッセージが届き、処理できるようになりました

これは、TCPオプション(NODELAYなど)、MTU制限などに関係なく機能します。

于 2011-07-07T09:31:22.107 に答える