2011-10-28 18 views
0

私はソケットプログラミングを使って通信する2つのプログラムを持っています。当初は番号を指定します。互いの間でメッセージを交換しなければならない時間についてのホップの数である。メッセージを受け取るたびに、そのIDをメッセージに追加します。したがって、文字列は毎回サイズが大きくなります。私のプログラムは8000ホップで正常に動作していますが、プログラムp1は長さ16388の文字列を送りますが、8000を超えると、p2はソケットに16385しか読み込めないことを示します。私はioctl()を使用して、ソケットでrecv()の準備ができている文字の量を決定し、次にchar *変数でrecvします。recv()内の遅延

p1のsend rec2()はp2で、p2はソケット内の16385文字だけを識別しますか? EXのために

: P1は、長さを送信する場合(16388)

P2のみを以下の長さ(16385)

+0

UDP、TCPまたはその他のソケット?また、ioctl()を使用して文字を取得することもできます。これはp2が16385バイトだけを識別する方法ですか? – Jake

+0

@Jake:ソケットの作成にはSOCK_STREAMを使用します。 p1は16388を送信しますが、ioctl()は16385だけを見るので、混乱しています。 –

答えて

5

を受けたが、私はあなたに8個のカボチャを送信しようとしていると言います。私はテーブルの上にそれらの6を入れます。あなたは、「私は8個のパンプキンを期待しています.6時ではないと思います。最後の2個をテーブルに置くまで待つつもりです。 「一度に飛行機にあまりにも多くのカボチャが欲しいとは思っていませんが、最後の2台をテーブルに置く前に、6台のうち2台を使うまで待つでしょう。私たちは立ち往生しています。私たちはそれぞれ相手を待っています。永遠に待つよ。

すでに受信したバイトを受け入れる前に、より多くのバイトが受信されるまで待つことはできません。この理由は簡単です。ネットワークプロトコルによって、各側がもう片方を待つことはできません。 TCPは送信側がこのコンテキストで待機することを許可するので、受信側も同様に待機することができません。

受信したバイトを受け入れます。それらのいずれかを受け入れる前に、相手側がすべてを送信するのを待つ必要はありません。それ以外の場合は、相手側が最初のものを受け入れるのを待ってから、それ以上送信するとどうなりますか?

+0

私はSOCK_STREAMを使用します。また、ioctlを使用して、読み込み可能なバイト数を手前で知っています。問題は今、ioctl()がP2でより少ない数を識別するので、私はP1によって送られた文字列全体を取得しないということです。あなたは「相手が一気にすべてを送るのを待ってはいけない」とはどういう意味ですか?一度にP1によって送信されたすべてのデータを受け取ることを目的とした単一のrecv()関数があります。> VALGRINDでプログラムを実行すると、この動作が発生しません。 P2は、P1が正確に送信しているすべてを受信することができ、プログラムは正しく動作します。 –

+1

すべてのデータを一度に受信することはできません。送信者は、最初の部分を受け入れるまで、最後の部分の送信を拒否することができます。したがって、あなたは最後の部分を送るまで、最初の部分を受け入れることを拒否することは許されません。はい、時にはうまくいく、時にはうまくいかないこともあります。あなたがルールに従えば、毎回動作します。 –

+0

あなたはメッセージの最後に到達するまでrecv()を行うことをお勧めしますが、これは '\ 0'終了を意味しますか? –

0

おそらくカーネルバッファの上限に達しています。あなたはおそらくSO_RCVBUFを受信機で増やすことができ、期待どおりに動作します:SIOCINQは最終的に未読データのフルサイズを返します。

しかし、正しく機能するようにするべきではありません。バッファを混乱させるのは、パフォーマンスを微調整したいときだけです。

カーネルに使用可能なバイト数を尋ねる必要がないように、コードを再構成する必要があります。合理的な制限(4096など)を読み、1つのアプリケーションレベルのメッセージを複数の部分に分割して処理します。メッセージの長さ/境界が必要な場合は、TCPの上に自分自身を実装する必要があります。

ここで長ヘッダーとメッセージを読むためにいくつかの愚かなコードです。

int ret, len = 0, have_read; 
have_read = 0; 
while (have_read < sizeof(len)) { 
    // This will likely always return sizeof(len) the first time. 
    ret = read(fd, ((char*)&len) + have_read, sizeof(len) - have_read); 
    if (ret <= 0) { 
     // Handle error. 
    } 
    have_read += ret; 
} 
char* buf = malloc(len); 
if (!buf) { 
    // Handle error. 
} 
have_read = 0; 
while (have_read < len) { 
    ret = read(fd, buf + have_read, len - have_read); 
    if (ret <= 0) { 
     // Handle error. 
    } 
    have_read += ret; 
} 
// Handle message in buf. 
+0

recv()のバッファにデータを受け取るためにmalloc()を実行できるように、使用可能なバイト数を調べる必要があります。 私の目的は、ioctl()を使ってバッファを読み込み、変数をmalloc()してデータを受け取ることで、p1がどれだけのデータを送るかを事前に知ることでした。 しかし、間違ったサイズが返されるので、私のコードのロジックに問題があります。 –

+0

@ManojKumar - サイズは間違っていません。そのioctlは、tcpバッファーですぐに使用できるバイト数ですが、これは限られています。報告されたすべてのデータを読むと、さらに多くのデータが表示されます。メッセージの全体サイズをmallocする必要がある場合は、長さを別々のヘッダーに書き込み、複数の読み取り呼び出しでバッファーを埋める。 mallocを使用せずにデータを処理することを検討する必要があります。 – cdleonard

+0

しかし、私はP1から2つの異なるsend()でメッセージと長さを区切っていると、メッセージが一緒に集まってくることがあります。 P2はそれらを単一のメッセージとして認識し、P2は次のrecv()で無期限に待機し始めます。したがって、長さとメッセージの両方を単一のエンティティにパックする必要がありました。だから私のioctlは、データ全体を見ることはできません。 recv()で取得するデータのサイズや、recv()でp2のデータ全体を取得する方法を知るにはどうすればよいですか? –