TCPのバイトストリームとフレーミング設計の知識マップ(知識グラフ)
type: Dataset
description: TCP通信で、送信側がSend/Writeした単位ごとに受信側でReceive/Readできるという思い込みが、分割・結合・文字化け・プロトコル破損を引き起こすことを扱う。TCPが運ぶのは順序付きのバイトストリームであり、メッセージ境界は保証されないため、受信側はアプリケーションプロトコルとしてフレーミング(固定長・区切り文字・長さプレフィックス・自己記述形式)でメッセージ境界を決める必要がある。Socket.NoDelayやDataAvailable、TLSのレコード単位はいずれもメッセージ境界の代わりにはならない。実装では、Read/Receiveの戻り値のバイト数だけを信用し、必要バイト数を読み切るまでループする設計と、本番でだけ壊れる不具合をWiresharkやpktmonで観測する手順が実務の要点になる。

TCPのバイトストリーム性
type: Concept
definition: TCPが保証するのは送ったバイト列が順序を保って重複・欠落なく届くことだけであり、送信側のSend単位を受信側のReceive単位として保存することは保証しないという性質である。
alternative label: TCPは順序付きのバイトストリーム
may cause: 送信区切りと受信区切りのずれ(分割・結合)

アプリケーションプロトコルのフレーミング
type: Concept
definition: 受信側が、受け取ったバイト列のどこからどこまでが1メッセージなのかを判断する、アプリケーションプロトコル側の仕組みである。
alternative label: フレーミング
alternative label: メッセージ境界の決定
prevents: 送信区切りと受信区切りのずれ(分割・結合)

長さプレフィックス方式
type: Concept
definition: メッセージの先頭に本文長を置き、そのバイト数だけ本文を読むフレーミング方式で、任意のバイナリを含められ最大サイズ制限も入れやすい。
alternative label: 長さプレフィックス
implements: アプリケーションプロトコルのフレーミング
recommended for: TCPのバイトストリーム性
requires: 必要バイト数まで読み切る/書き切るループ

送信区切りと受信区切りのずれ(分割・結合)
type: Concept
definition: TCPの送信単位と受信単位が一致しないために、1メッセージが複数回の受信に分割されたり、複数メッセージが1回の受信に結合されたりする現象である。
alternative label: 分割・結合
alternative label: フレーミングの不具合
verified by: Wireshark
verified by: Packet Monitor(pktmon)

固定長方式
type: Concept
definition: 常に決まったバイト数を1メッセージとするフレーミング方式で、境界は明確だが可変長データを扱いにくい。
alternative label: 固定長電文
implements: アプリケーションプロトコルのフレーミング
requires: 必要バイト数まで読み切る/書き切るループ

区切り文字方式
type: Concept
definition: 改行など特定のバイト列までを1メッセージとするフレーミング方式である。
alternative label: 改行区切り
implements: アプリケーションプロトコルのフレーミング
requires: 必要バイト数まで読み切る/書き切るループ

自己記述形式
type: Concept
definition: HTTPのContent-Lengthやchunkedのように、形式そのものの中に長さや終端を表す情報を持たせるフレーミング方式である。
alternative label: Content-Length
alternative label: chunked
implements: アプリケーションプロトコルのフレーミング

Nagleアルゴリズム(Socket.NoDelay)
type: Concept
definition: 小さな送信をまとめて送るかどうかを調整するアルゴリズムで、Socket.NoDelayをtrueにすると無効化できる送信遅延・効率に関する設定である。
alternative label: Socket.NoDelay
alternative label: Nagle
not recommended for: アプリケーションプロトコルのフレーミング

NetworkStream.DataAvailable
type: Concept
definition: その瞬間にローカルの受信バッファに読み取り可能なデータがあるかどうかだけを示す、.NETの NetworkStreamのプロパティである。
alternative label: DataAvailable
not recommended for: アプリケーションプロトコルのフレーミング

TLSレコード
type: Concept
definition: TLSが暗号化通信を運ぶ際に使う内部的な伝送単位で、アプリケーションメッセージの境界とは一致しない。
alternative label: TLS Record
not recommended for: アプリケーションプロトコルのフレーミング

並行Writeによるアプリケーションレベルの混線
type: Concept
definition: 同じTCP接続に対して複数のタスクが同時にフレームを書き込むと、ヘッダーと本文の順序が混ざってしまう問題である。
alternative label: 並行書き込みの混線
may cause: 送信区切りと受信区切りのずれ(分割・結合)

必要バイト数まで読み切る/書き切るループ
type: Concept
definition: Read/ReceiveやSend/Writeの戻り値が要求したサイズより少ないことがあるため、目的のバイト数に達するまで繰り返し呼び出す実装パターンである。
alternative label: ReadUntilFullOrEndAsync
alternative label: SendAllAsync
alternative label: Stream.ReadExactly
prevents: 送信区切りと受信区切りのずれ(分割・結合)

非同期I/O
type: Concept
definition: 要求を発行した呼び出しがI/Oの完了を待たずにすぐ戻り、完了を別途の通知(イベント・APC・I/O完了ポートなど)で受け取るI/Oの形態。
alternative label: Asynchronous I/O
alternative label: オーバーラップI/O

Wireshark
type: Concept
definition: キャプチャしたパケットをパケット詳細ペインとバイト列ペインで対応づけて表示できる、パケット解析ツール。

Packet Monitor(pktmon)
type: Concept
definition: Windows標準でパケットキャプチャができるツールで、取得したETLはpcapngに変換してWiresharkで開ける。
alternative label: pktmon.exe

Npcap
type: Concept
definition: Windowsでループバック(127.0.0.1)のトラフィックをキャプチャするために必要なパケットキャプチャドライバーである。
alternative label: Npcap driver

subject: TCPのバイトストリーム性
predicate: mayCause
object: 送信区切りと受信区切りのずれ(分割・結合)
description: TCPは送ったバイト列の順序・重複なし・欠落なしの到達だけを保証し、Sendした単位がReceiveの単位として保存されることは保証しないため、分割や結合が起こり得る
evidence: rfc9293.html
verified at: 2026-08-01
certainty: established

subject: アプリケーションプロトコルのフレーミング
predicate: prevents
object: 送信区切りと受信区切りのずれ(分割・結合)
description: 受信側でメッセージ境界を判断する仕組み(フレーミング)を設ければ、分割・結合によるメッセージ境界のずれに正しく対応できる
evidence: rfc9293.html
verified at: 2026-08-01
certainty: established

subject: 固定長方式
predicate: implements
object: アプリケーションプロトコルのフレーミング
description: 固定長方式は、常に決まったバイト数を1メッセージとすることでフレーミングを実現する
evidence: rfc9293.html
verified at: 2026-08-01
certainty: established

subject: 区切り文字方式
predicate: implements
object: アプリケーションプロトコルのフレーミング
description: 区切り文字方式は、改行など特定のバイト列までを1メッセージとすることでフレーミングを実現する
evidence: rfc9293.html
verified at: 2026-08-01
certainty: established

subject: 長さプレフィックス方式
predicate: implements
object: アプリケーションプロトコルのフレーミング
description: 長さプレフィックス方式は、先頭に本文長を置きそのバイト数だけ本文を読むことでフレーミングを実現する
evidence: rfc9293.html
verified at: 2026-08-01
certainty: established

subject: 自己記述形式
predicate: implements
object: アプリケーションプロトコルのフレーミング
description: 自己記述形式は、HTTPのContent-Lengthのように形式内に長さや終端の情報を持たせることでフレーミングを実現する
evidence: rfc9110.html
verified at: 2026-08-01
certainty: established

subject: 長さプレフィックス方式
predicate: recommendedFor
object: TCPのバイトストリーム性
description: 独自プロトコルを作るなら、本文に任意のバイナリを含められ、受信側の実装が明確で、最大サイズ制限も入れやすい長さプレフィックス方式がまず検討候補になる
evidence: rfc9293.html
verified at: 2026-08-01
certainty: established

subject: Nagleアルゴリズム(Socket.NoDelay)
predicate: notRecommendedFor
object: アプリケーションプロトコルのフレーミング
description: Socket.NoDelay(Nagleアルゴリズムの無効化)は送信の遅延・効率の調整であり、メッセージ境界を保存する設定ではないため、フレーミングの代わりにはならない
evidence: https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.nodelay
verified at: 2026-08-01
certainty: established

subject: NetworkStream.DataAvailable
predicate: notRecommendedFor
object: アプリケーションプロトコルのフレーミング
description: DataAvailableはその瞬間にローカル受信バッファに読み取り可能なデータがあるかを示すだけで、アプリケーション上の1メッセージが完了したことを意味しない
evidence: https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.networkstream.dataavailable
verified at: 2026-08-01
certainty: established

subject: TLSレコード
predicate: notRecommendedFor
object: アプリケーションプロトコルのフレーミング
description: TLSレコードは内部的な伝送単位であり、アプリケーションメッセージの境界ではないため、TLS化してもアプリケーション層でのフレーミング設計は必要になる
evidence: rfc8446.html
verified at: 2026-08-01
certainty: established

subject: 並行Writeによるアプリケーションレベルの混線
predicate: mayCause
object: 送信区切りと受信区切りのずれ(分割・結合)
description: 同じTCP接続に複数タスクが同時にフレームを書き込むと、ヘッダーと本文が混ざるアプリケーションレベルの混線が起き、受信側のフレーム復元が壊れる
evidence: rfc9293.html
verified at: 2026-08-01
certainty: established

subject: 必要バイト数まで読み切る/書き切るループ
predicate: prevents
object: 送信区切りと受信区切りのずれ(分割・結合)
description: Read/Receiveの戻り値のバイト数だけを信用し、必要なバイト数を読み切るまでループすることで、途中で切れた受信を1メッセージとして誤処理しない
evidence: https://learn.microsoft.com/en-us/dotnet/api/system.io.stream.readexactly
verified at: 2026-08-01
certainty: established

subject: 必要バイト数まで読み切る/書き切るループ
predicate: uses
object: 非同期I/O
description: ReadAsync/WriteAsyncのような非同期I/Oを使う場合でも、要求サイズに届くまで読み書きを繰り返すという考え方は同じである
evidence: https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.networkstream.read
verified at: 2026-08-01
certainty: context-dependent

subject: 送信区切りと受信区切りのずれ(分割・結合)
predicate: verifiedBy
object: Wireshark
description: Follow > TCP Streamで復元したバイト列を見て、送信側のフレーム組み立てと受信側の復元処理のどちらが壊れているかを切り分けられる
evidence: Loopback
verified at: 2026-08-01
certainty: established

subject: 送信区切りと受信区切りのずれ(分割・結合)
predicate: verifiedBy
object: Packet Monitor(pktmon)
description: Windows標準のpktmonでキャプチャしたETLをpcapngに変換し、Wiresharkで開いて同様に確認できる
evidence: pktmon
verified at: 2026-08-01
certainty: established

subject: 長さプレフィックス方式
predicate: requires
object: 必要バイト数まで読み切る/書き切るループ
description: 4バイトヘッダーも本文も分割され得るため、ヘッダーと本文それぞれを読み切るまでのループが前提になる
evidence: https://learn.microsoft.com/en-us/dotnet/api/system.io.stream.readexactly
verified at: 2026-08-01
certainty: established

subject: 固定長方式
predicate: requires
object: 必要バイト数まで読み切る/書き切るループ
description: 固定長方式でも、1回のReadAsyncで指定バイト数がすべて返るとは限らないため、読み切るまでのループが必要になる
evidence: https://learn.microsoft.com/en-us/dotnet/api/system.io.stream.readexactly
verified at: 2026-08-01
certainty: established

subject: 区切り文字方式
predicate: requires
object: 必要バイト数まで読み切る/書き切るループ
description: 改行が来るまでバイトを蓄積し、1行分そろってからデコードするなど、区切りが確認できるまで読み続ける実装が必要になる
evidence: rfc9293.html
verified at: 2026-08-01
certainty: established

subject: Wireshark
predicate: requires
object: Npcap
description: Windowsでループバック(127.0.0.1)を見るにはNpcapが必要になる
evidence: Loopback
verified at: 2026-08-01
certainty: context-dependent