1

C++ソケットの読み取りをどのようにループしますか。

stringstream ss;
while (1) {
    char buf [2];
    ssize_t e = read(fd, buf, 2);

    ss << buf[0];
    ss << buf[1];



    cout << e << endl;
    cout << buf[0] << endl;
    cout << buf[1] << endl;

    if (e <= 0) {
        break;
    }
}
string msg = "";
ss >> msg;

telnetでhelloと入力してから、これをテストするために入力すると、次のようになります。

2
h
e
2
l
l
2
o

1

そして、それはただそこで待機し、ループしません。何が起こっているのですか、そしてどのようにソケットを読み取るのですか?

を使用してEOFを表すにはどうすればよいですか

  1. telnet

  2. write(fd、buf、bufSize);のコンテキストでのbuf。

4

3 に答える 3

1

ループしないってどういうこと?もう少し入力してEnterキーを押すと、さらに出力が表示されます..

終了したら、Ctrl+D を押して入力の終了 (EOF) を知らせる必要があります。

于 2012-05-10T08:38:49.567 に答える
1

を使用して EOF を示すにはどうすればよいですか

1) テルネット

2) write(fd, buf, bufSize) のコンテキストでの buf;

まず、通知したいのは EOF ではありません。それは「メッセージの終わり」または「受信したばかりのデータは完全なプロトコル データ ユニットであり、それを処理する必要があります」です。そして答えは、双方が同意する限り、あなたが望むものです。

たとえば~、メッセージの終わりを示すために特別に文字を予約することができます。メッセージの終わりを示すために、一方が~. 反対側は、 を受信する~と、それより前のすべてが単一のメッセージであり、それ以降のすべてが新しいメッセージであることを認識しています。

実際のメッセージを送信する前に、メッセージの長さを送信することもできます。0 バイトまたは改行が続くテキストで行うことができます。または、各メッセージを 1 行にすることもできます。

あなたはそれを行うことができますが、特定のアプリケーションでは最も理にかなっていますが、実際にはそれを行う必要があります.

TCP がそれを行う 2 つのケースがあります。

1) 一方が完全に送信を完了し、もう一方の側がそれ以上データを送信しないことがわかっている場合close、ソケットで使用できます。反対側は、送信済みの残りのデータを読み取ってから、readを返し0ます。

2) 一方がこれ以上データを送信しないが、もう一方の側がさらにデータを送信する可能性がある場合shutdown、接続のその側を送信できます。ただし、これ以上データを送信することはできません。反対側はこのシャットダウンを認識し、そのように特別にコーディングされていれば、半分をシャットダウンするまでデータを送信し続けることができます。次に、反対側readはゼロを返します。(これを受け取るように設計されていないプログラムに対してこれを行うと、おそらく混乱し、データを送信できることに気付かないことに注意してください。)

それ以外の場合は、すべてあなた次第です。

于 2012-05-10T09:11:45.413 に答える
0

TCP パケットはストリームであり、ファイルではありません。ストリームをどのように読むかはあなた次第です。

一般に、一方の端で 20 バイトを書き込むと、もう一方の端で 1 回の読み取りで 20 バイトが取得され、一般的な tcp/ip オプションの使用が制限されます。

以下に仮定があります。仮定のいくつかは次のとおりです。

すべての足場コードがそこにあると仮定します。

私が間違いを犯したと仮定して、自分でデバッグしてください。

すべてのバイト オーダーの問題が処理されると仮定します。

浮動小数点型をバイナリとして送信しないほど賢いと仮定します。

  • 一部のプログラマーは、長さのプレフィックス付きパケットを使用し、長さ byte(2) を読み取ってから、その長さが表すバイト数だけ読み取ることを選択します。

     unsigned char buffer[MAX_CHAR] = "";
     unsigned char length = 0;
     int bytesRead = 0;
    
     read( fd, sizeof( length ), &length );
     // Handle failure from read
     while( bytesRead < length )
     {
         int readRv = read( fd, &buffer[bytesRead], length - bytesRead );
         if( readRv <= 0 )  // 0 usually means socket was closed. -1 is an erro
         {
             // Handle socket error/closed socket
         }
         else if( readRv < length )
         {
             bytesRead += readRv;
         }
         else if( readRv == length )
         {
             bytesRead = readRv;
             break;
         }
     }
    
  • 一部のプログラマーは、利用可能なものを読み取り、パケット マーカーの終わりを探します。

     unsigned char buffer[MAX_CHAR] = "";
     unsigned char length = 0;
     int bytesRead = 0;
     int readRv = read( fd, buffer, sizeof( buffer ) );
     int eopFound = 0;
    
    
     if( (eopFound = findEndOfPacketMarker( buffer )) > 0 )
     {
         // Less than 0 = error.
     }
     else if( eopFound == 0 )
     {
         // No end of packet, must read more bytes here
     }
     else
     {
         // Found an end of packet marker
     }
    
     // Here you deal with bytes that are "over read"
     // Either the
     // 1) packet was bigger than buffer,
     // 2) there were bytes left over after the EOP marker
     // 3) Martians crapped in your code and screwed it all up. :)
    
  • 一部のプログラマーは、固定サイズのパケット セットとパケット タイプ ID を使用します。

    int packetType;
    
     unsigned char buffer[MAX_CHAR] = "";
     unsigned char length = 0;
     int bytesRead = 0;
    
     read( fd, sizeof( packetType ), &packetType );
     read( fd, getLengthFromPacketType( packetType ), buffer );
    

それはほとんどのことをカバーするはずです...さらに質問がある場合は、コメントで@JimRのことを聞いてください。私が読むメッセージとして表示されます.

于 2012-05-10T10:13:56.073 に答える