知識マップ: TCPでSendした単位ごとにReceiveできるという誤解 ── バイトストリームとして扱うための受信設計
記事「TCPでSendした単位ごとにReceiveできるという誤解 ── バイトストリームとして扱うための受信設計」の主張を、概念と関係(エッジ)に分解した知識グラフの全体です。各関係には根拠・確認日・確度が付いています。
TCP通信で、送信側がSend/Writeした単位ごとに受信側でReceive/Readできるという思い込みが、分割・結合・文字化け・プロトコル破損を引き起こすことを扱う。TCPが運ぶのは順序付きのバイトストリームであり、メッセージ境界は保証されないため、受信側はアプリケーションプロトコルとしてフレーミング(固定長・区切り文字・長さプレフィックス・自己記述形式)でメッセージ境界を決める必要がある。Socket.NoDelayやDataAvailable、TLSのレコード単位はいずれもメッセージ境界の代わりにはならない。実装では、Read/Receiveの戻り値のバイト数だけを信用し、必要バイト数を読み切るまでループする設計と、本番でだけ壊れる不具合をWiresharkやpktmonで観測する手順が実務の要点になる。
flowchart LR
accTitle: TCPのバイトストリームとフレーミング設計の知識マップ
accDescr: TCPがバイトストリームでありSend単位を保証しないこと、フレーミング方式の種類、NoDelayやDataAvailableやTLSレコードが境界の代わりにならないこと、WiresharkやpktmonでのAudit手順との関係を示す図
tcp_byte_stream["TCPのバイトストリーム性"]
application_framing["アプリケーションプロトコルのフレーミング"]
length_prefix_framing["長さプレフィックス方式"]
message_boundary_mismatch["送信区切りと受信区切りのずれ(分割・結合)"]
fixed_length_framing["固定長方式"]
delimiter_framing["区切り文字方式"]
self_describing_framing["自己記述形式"]
nagle_algorithm["Nagleアルゴリズム(Socket.NoDelay)"]
socket_dataavailable["NetworkStream.DataAvailable"]
tls_record["TLSレコード"]
concurrent_write_interleaving["並行Writeによるアプリケーションレベルの混線"]
io_loop_until_complete["必要バイト数まで読み切る/書き切るループ"]
asynchronous_io["非同期I/O"]
wireshark["Wireshark"]
pktmon["Packet Monitor(pktmon)"]
npcap["Npcap"]
tcp_byte_stream -->|"原因になり得る"| message_boundary_mismatch
application_framing -->|"防止する"| message_boundary_mismatch
fixed_length_framing -->|"実装を担う"| application_framing
delimiter_framing -->|"実装を担う"| application_framing
length_prefix_framing -->|"実装を担う"| application_framing
self_describing_framing -->|"実装を担う"| application_framing
length_prefix_framing -->|"推奨される対応"| tcp_byte_stream
nagle_algorithm -->|"用いるのは非推奨"| application_framing
socket_dataavailable -->|"用いるのは非推奨"| application_framing
tls_record -->|"用いるのは非推奨"| application_framing
concurrent_write_interleaving -->|"原因になり得る"| message_boundary_mismatch
io_loop_until_complete -->|"防止する"| message_boundary_mismatch
io_loop_until_complete -.->|"利用する"| asynchronous_io
message_boundary_mismatch -->|"で確認できる"| wireshark
message_boundary_mismatch -->|"で確認できる"| pktmon
length_prefix_framing -->|"前提とする"| io_loop_until_complete
fixed_length_framing -->|"前提とする"| io_loop_until_complete
delimiter_framing -->|"前提とする"| io_loop_until_complete
wireshark -.->|"前提とする"| npcap
概念間の関係(全19件)
図と同じ関係を文章でも列挙します。表示している文と機械可読な意味データ(RDFa)は同じ要素に載っています。確度が「確立した関係」のものは直接の関係として、「条件付きの関係」のものは成立条件つきの言明(rdf:Statement)として表現しています。
- TCPのバイトストリーム性は送信区切りと受信区切りのずれ(分割・結合)の原因になることがあります。
- アプリケーションプロトコルのフレーミングは送信区切りと受信区切りのずれ(分割・結合)を防ぎます。
- 固定長方式はアプリケーションプロトコルのフレーミングの実装を担います。
- 区切り文字方式はアプリケーションプロトコルのフレーミングの実装を担います。
- 長さプレフィックス方式はアプリケーションプロトコルのフレーミングの実装を担います。
- 自己記述形式はアプリケーションプロトコルのフレーミングの実装を担います。
- 長さプレフィックス方式はTCPのバイトストリーム性に対する本記事の推奨です。
- Nagleアルゴリズム(Socket.NoDelay)をアプリケーションプロトコルのフレーミングに用いることは推奨されません。
- NetworkStream.DataAvailableをアプリケーションプロトコルのフレーミングに用いることは推奨されません。
- TLSレコードをアプリケーションプロトコルのフレーミングに用いることは推奨されません。
- 並行Writeによるアプリケーションレベルの混線は送信区切りと受信区切りのずれ(分割・結合)の原因になることがあります。
- 必要バイト数まで読み切る/書き切るループは送信区切りと受信区切りのずれ(分割・結合)を防ぎます。
- 必要バイト数まで読み切る/書き切るループは非同期I/Oを利用します。
- 送信区切りと受信区切りのずれ(分割・結合)はWiresharkで確認できます。
- 送信区切りと受信区切りのずれ(分割・結合)はPacket Monitor(pktmon)で確認できます。
- 長さプレフィックス方式は必要バイト数まで読み切る/書き切るループを前提とします。
- 固定長方式は必要バイト数まで読み切る/書き切るループを前提とします。
- 区切り文字方式は必要バイト数まで読み切る/書き切るループを前提とします。
- WiresharkはNpcapを前提とします。
主要概念の定義
機械可読データ
このページはサイトの知識グラフ(_data/knowledge/)から自動生成されています。誤りの指摘はお問い合わせからお願いします。