1

私のクライアントサーバーアプリケーションでは、パケットを作成してクライアント経由でサーバーに送信する方法を知りました

次に、サーバー上で、これがどのパケットであるかを認識し、適切なリプレイを送信します

しかし、突然このトピックに出くわし、この問題に陥るのではないかと心配しています

問題

TCP/IP のプロトコルを設計する人々が初心者に犯す最も一般的な間違いの 1 つは、メッセージ境界が保持されていると想定することです。たとえば、単一の「送信」は単一の「受信」になると想定しています。

一部の TCP/IP ドキュメントは、部分的に責任があります。多くの人が、TCP/IP がどのようにパケットを保持するかについて読んでいます。必要に応じてパケットを分割し、受信側で再順序付けして再組み立てします。これは完全に真実です。ただし、1 回の「送信」では 1 つのパケットは送信されません。

通常、クライアントとサーバーが同じマシン上にある場合、単一の「送信」が実際には単一の「受信」に対応するほど高速に通信するため、ローカル マシン (ループバック) テストでこの誤解が確認されます。残念ながら、これは単なる偶然です。

この問題は通常、ソリューションをインターネットに展開しようとするとき (クライアントとサーバー間の遅延が増加する)、または大量のデータを送信しようとするとき (断片化が必要) に現れます。残念ながら、この時点でプロジェクトは通常最終段階にあり、アプリケーション プロトコルが公開されていることもあります。

実話: 私はかつて、カスタム クライアント/サーバー ソフトウェアを開発する会社で働いていました。元の通信コードは、このよくある間違いを犯していました。ただし、それらはすべてハイエンド ハードウェアを備えた専用ネットワーク上にあったため、根本的な問題が発生することはほとんどありませんでした。そうなった場合、オペレーターは「バグのある Windows OS」または「別のネットワーク障害」と言って再起動するだけでした。この会社での私の仕事の 1 つは、コミュニケーションを変更して、より多くの情報を含めることでした。もちろん、これにより問題が定期的に発生し、アプリケーション プロトコル全体を変更して修正する必要がありました。本当に驚くべきことは、このソフトウェアが無数の年中無休の自動化システムで 20 年間使用されてきたことです。それは根本的に壊れていて、誰も気づきませんでした。

では、AUTH_CALC、VALUE1 = 10、VALUE2 = 12パケットのようなものを送信して、サーバーから安全な方法で受信するにはどうすればよいですか...

そして、私がここでやっていることの例が欲しいなら、それは以下にあります

[クライアント]

Send(Encoding.ASCII.GetBytes("1001:UN=user123&PW=123456")) //1001 is the ID

[サーバ]

private void OnReceivePacket(byte[] arg1, Wrapper Client)
{
    try
    {
        int ID;
        string V = Encoding.ASCII.GetString(arg1).Split(':')[0];
        int.TryParse(V, out ID);

        switch (ID)
        {
            case 1001://Login Packet
                AppendToRichEditControl("LOGIN PACKET RECEIVED");
                break;

            case 1002:
                //OTHER IDs
                break;

            default:
                break;
        }
    }
    catch { }         
}

これは、メッセージを構造化し、サーバー上で処理するための良い方法ですか?

また、ASCIIまたはUTF8を使用するのにどちらがより良いエンコーディングですか?

4

1 に答える 1

1

あなたができる最善の方法は、長さインジケーターを使用することです。10000バイトのファイルを送信するとし、最初にファイルの長さを送信し、反対側からack、つまり「OK」文字列を受信して​​から、チャンクごとに10,000バイトを送信し続けます(おそらく、uは4096バイトかかる可能性があります)。毎回4096バイトを2回送信し、最後のチャンクで2000奇数バイトを送信します。受信側では、1回の送信で4096バイト全体を受信するという保証はありません。したがって、uが4096バイトを取得するまで待ってから、次の4096バイトに進む必要があります。

于 2012-09-10T05:54:56.633 に答える