2

c/c++でwin socketを使ったチャットプログラムを作りたいです。(私はまったくの初心者です。) 最初の質問は、クライアントがサーバーからパケットを受信したかどうかを確認する方法についてです。たとえば、サーバーは「aaaa」をクライアントに送信します。クライアントがパケット「aaaa」を受信しない場合、サーバーはパケットを再送信する必要があります。とはいえ、調べ方がわかりません。これが私の考えの打撃です。最初のケース。


サーバー --- "aaaa" ---> クライアント。
サーバーは、クライアントからの確認メッセージの待機時間のようなものをチェックします。
クライアント --- 「受け取りました」 ---> サーバー。
サーバーはパケットを再送信しません。


他のケース。
サーバー --- "aaaa" ---> クライアント。
サーバーはタイムアウトするまでクライアント メッセージを待機してい
ます サーバー --- "aaaa" ---> クライアントが再び。

しかし、これらはおそらく不適切です。2 番目のケースを見てください。サーバーはクライアントからのメッセージをしばらく待っています。タイムアウトになると、サーバーはパケットを再送信します。この場合、クライアントはパケットを 2 回受信する可能性があります。

2 番目の質問は、無制限のサイズのパケットを送信する方法です。本には、パケットにはタイプ、サイズ、およびメッセージが必要であると書かれています。それに続いて、特定のサイズのメッセージしか送信できません。でも1Mbyte以上のメッセージを送りたい(無制限)

どうやってするか?

誰でも良いリンクを持っているか、正しいロジックをできるだけ簡単に説明してください。

ありがとう。

4

2 に答える 2

1

最初の部分では、TCP を見てください。順序付けされた信頼性の高いパケット転送を提供します。さらに、UDP を使用して自分で実装することで、多くのカスタマイズを行うことができます。大まかに言えば、それが行うことは、

サーバー: 1. 各パケットに番号を付けて送信します。 2. 特定のパケット番号の確認応答を待ちます。そして、失われたパケットを再送信します。

クライアント: 1. パケットを受信し、バッファを維持します (スライディング ウィンドウ) 2. バッファがオーバーフローするか、間違ったシーケンスのパケットが到着するまで、バッファ内のパケットを収集し続けます。それが発生するとすぐに、正しいシーケンスのパケットが「配信」され、最後の正しいパケットのシーケンス番号が確認応答とともに送信されます。

2 番目の部分: HTTP を使用します。いくつかの変更を加えて。送信が完了したことをクライアントに伝えるための非常にユニークなインジケーターが必要です。

于 2013-08-06T02:31:52.130 に答える
1

TCP を使用します。パケットではなく、アプリケーション レベルで「メッセージ」を考えてください。

TCP はすでにネットワーク レベルのパケット データ、エラー チェック、および失われたパケットの再送信を処理しています。これはバイトの「ストリーム」としてアプリケーションに提示されますが、必ずしも配信が保証されるわけではありません (いずれかの端が強制的に切断される可能性があるため)。

したがって、アプリケーション レベルでは、メッセージの受信とバッファリングを処理する必要があります。再接続するクライアントは、(まだ) 正しく受信されていない以前のメッセージを要求できます。

以下にいくつかのデータ構造を示します。

class or struct Message {
    int type;              // const MESSAGE.
    int messageNumber;     // sequentially incrementing.
    int size;              // 4 bytes, probably signed;  allows up to 2GB data.
    byte[] data;
}

class or struct Receipt {
    int type;              // const RECEIPT.
    int messageNumber;     // last #, successfully received.
}

Connect/ Hello と、おそらく Disconnect/ Goodbye ハンドシェイクも必要になる場合があります。

class Connect {
    int type;              // const CONNECT.
    int lastReceivedMsgNo; // last #, successfully received.
    // plus, who they are?   
    short nameLen;
    char[] name;
}

本当に単純で、再接続するクライアントにメッセージをバッファリング/再送信する必要がない場合は、さらに単純になります。

また、すべてのメッセージまたはハンドシェイクの最初の 2 つのフィールドとして TYPE と SIZE (4 バイトの int) を持つ「均一なメッセージ構造」を採用することもできます。これは、いくつかの冗長性を犠牲にして、これらを処理するためのルーチンを標準化するのに役立つ場合があります (たとえば、「名前」フィールドサイズ)。

于 2013-08-06T02:40:05.597 に答える