質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.04%

TCP/IP受信にて、2電文つながったデータを受信したら、2電文受信できない。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 8,715

score 41

お世話になります。 C#にて、TCP/IP通信処理を行っております。 以下のような処理にて、一回の受信に、2つ電文がくっついて受信した場合、1電文づつ取得できずに、アプリケーションエラーとなります。

Socket.Receive を利用して、指定バイト数の受信は、保障されていると考えておりますが、 実は、指定バイト数以下でも受信することがありますでしょうか? ご教授お願いいたします。

以下ソースです。

protected bool DataRecv(Socket client, out byte[] data)
{
   int length = 0;
   data = null;

   if (client != null && client.Connected)
   {
     // ヘッダ部受信
      int recvLength = client.Receive(_recvData, Telegrams.TelegramHeader.TELEGRAM_HEADER_SIZE, 0);

      if (recvLength == 0)
      {
      // 0バイト受信(切断)  
        return false;  
      }

       // データ部受信準備  
       // 受信電文からデータ部の長さを取得する  
       int dataLength = (int)(((_recvData[15] << Telegrams.TelegramHeader.TELEGRAM_OCTET) & 0xff00) | _recvData[14]);  
       length = Telegrams.TelegramHeader.TELEGRAM_HEADER_SIZE + dataLength;  

       // 1電文の格納領域を確保  
        data   = new byte[length];

        //   ヘッダ部を作業領域にコピー  
        Array.Copy(_recvData, data, Telegrams.TelegramHeader.TELEGRAM_HEADER_SIZE);

        // データ部受信  
        recvLength = client.Receive(_recvData, dataLength, 0);


        return true;
        }
  }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ikuwow

    2015/12/04 13:10

    コードが見づらくなっていますので、Markdown記法でシンタックスハイライトしていただけると助かります。

    キャンセル

回答 2

checkベストアンサー

0

こういう低いレベルの関数は、受信したデータがあれば、それだけを返します。 データ長に100を指定していても、10バイト受信したら、第一引数のエリアに10バイトコピーして、その時点でリターンして10を返値とします。 150バイト受信したら、100バイトをコピーして、50バイトをOSの受信バッファに残し、100を返値としてリターンします。直後(次の受信前)に再度呼び出すと、残っている50バイトをコピーして50を返値としてリターンします。 つまり、引数で指定数長さは取得できるデータ長の最大値です。 欲しいだけのデータ長が出そろうまでループするように、自分で書く必要があります。

上記の説明で「受信したら」というデータは、OSの受信バッファに未取得のデータが残っていればその残っているデータのことで、OSの受信バッファが空でブロッキングモードの時は次に受信するまで待ってそのデータのことです。

なお、送信側で長いデータを1回で送信しても、受信側では短く何度にも分けて受信することがあります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/12/07 21:29

    コメントありがとうございます。Receiveで、指定する長さは、あくまで最大受信データ長なのですね。理解できました!

    キャンセル

0

available が非0である限り再読み込みしてくれ、って書いてありますよ。 memorystream か何かを引数に取るオーバーロードがあるんじゃないかと、検索したら無いですね。 じゃ基本に戻って、読み込みバッファサイズ1で available >0の間、 socket.recieve して、受信DATAを memorystreamにかきこみ、 完了したら、byte 配列にコンバートして返す処理、 バイト配列をヘッダとデータ部のセットに切り分ける処理、これも結果は配列になる、 この配列を逐次処理する、パケット解析する処理、

ですね。どこに書いてあるか?msdn 見てください。 socket.recieve のオーバーロード一覧、 memorystream、などでづ。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/12/04 13:59

    コメントありがとうございます。
    msdn 見てみます。

    キャンセル

  • 2015/12/04 22:41

    シリアル通信のように、1バイトづつ読み込んで、バッファに読み込ん処理することですね。Receveのパラメータに、レングスがあるため、必ず、指定レングスの受信バイト数を満たしたときに、Receve完了となると考えていました。指定レングスに満たさない時にも、Receve完了となるのでしょうか? 

    キャンセル

  • 2015/12/12 17:35

    自己レスです。
    テストプログラムを作成し、本件確認しました。socket recive メソッドの指定レングス以下でも受信されていました。受信バイト数は、あくまで、受信データを格納するエリアの最大バイト数を指定していることなのですね。

    受信バイト数をチェックし目的のデータ数を受信するようにします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る