

約24KBのTCPのデータを送信するとき、  
相手のウィンドウサイズが最大49640Byte(Wiresharkで確認)であるにも関わらず、  
8KB送信→8KB送信→3KB応答確認→+4KB応答確認→+5KB応答確認→8KB送信  
のようになっていました。  
この間他の通信は行われていませんでした。

約24KBを一度に送信しないのはどのような理由が考えられますでしょうか？


CC BY-SA 3.0
2016-10-20T15:34:19.630
29748
2017-03-05T08:10:40.677
19250
question
tcp
ウィンドウサイズ(送受信バッファ)に余裕があるのに応答確認を待つのはどんな時ですか？


  * 初期ウィンドウサイズが小さい (initcwnd)
  * TCPの送信バッファサイズが小さい

あたりはどうでしょうか。


CC BY-SA 3.0
2016-10-21T03:53:10.397
29761
2016-10-21T03:53:10.397
799
29748
answer


TCPでは通信帯域の輻輳を回避するためにTCP Slow
Startという制御をおこなっています。最初はゆっくりと送信を行い、通信相手からの応答確認が正常に届く間は一度に送信するデータを増やしていき、応答確認が届かなくなったら送信を減らすと言う制御をおこないます。

データサイズがもっと大きく数百KBあれば、16KB送信にたいする応答確認受信後は倍の32KB、次はさらに倍の64KBと一度に送信するサイズが増えていきます。


CC BY-SA 3.0
2016-11-03T03:01:10.417
30070
2016-11-03T03:01:10.417
12774
29748
answer


> 8KB送信→8KB送信→3KB応答確認→+4KB応答確認→+5KB応答確認→8KB送信

この動きを見る限り、Nagleアルゴリズムが効いているのではないでしょうか。  
Nagleアルゴリズムは以下の様に挙動します。

■Nagleアルゴリズムで送信が発生するケース（Wikiから抜粋）  
ケース１．未送信データが最大セグメントサイズ以上になる  
ケース２．過去の送信パケットで ACK が未受信の物がなくなる（TCP遅延ACKに注意）  
ケース３．タイムアウトになる

最初の８KB送信が２回続いているのは、最大セグメントサイズが８KBで設定されていて  
それを越えているからではないかと考えます。  
その後、送信しなくなるのは未送信データが最大セグメントサイズ以上では無いからだと思います。（ACK応答を待っている）  
送信バッファに関してですが、２４KBをsend()してその戻り値が２４KBだった場合は  
TCP送信としては受け付けられています。（送信バッファ不足ではない）

即座に送るべきデータを実行したい場合はTCP_NODELAYを使用することをオススメします。  
補足ですがNagleアルゴリズムは遅延ACKと相性が非常に悪いので通信が途切れるなど遅延するなどで問題が出る事がよくあります。


CC BY-SA 3.0
2017-03-05T08:10:40.677
33107
2017-03-05T08:10:40.677
20931
29748
answer