Winsock 10053 WSAECONNABORTED エラーと TCP の再送タイムアウト

Posted Thu Apr 03 2014

概要

会社でうちで作っている計測器と LAN で通信するソフトを作っていたのですが,通信が途中で途切れるというエラーに遭遇しました.ソフトは Windows で動作しアプリからコマンドを計測器に投げて,計測器側でコマンドに応じた処理を行い,処理結果をアプリに返すというものです.通信部分は Winsock で作っています.

計測器側での処理は最長で約60秒ほどかかりますが,プログラム上でソケットのタイムアウトを120秒に設定していました.全く問題無いと思っていたのですが実際に通信を行ってみると,約20秒程度経過した時点でタイムアウトが発生していました.

原因

デバッガで発生箇所を追ったところ,select 関数でタイムアウトを設定した後 recv 関数で返信を待っているときに戻り値で -1 を返していました.WSAGetLastError 関数にてエラーコードを取得したところ,10053 エラー WSAECONNABORTED のエラーコードを返していました.

エラーコードで調べてみたのですが,原因がわからず上司に確認してみたところ TCP/IP の再送タイムアウトというのが根本的な原因でした.

TCP/IP では通信相手からの確認応答がなかった場合にデータセグメントの再送を行うそうです.この再送回数を超えた場合,OS 側で通信が切断されてしまうようです.Windows ではデフォルトで 5 回に設定されており,この再送回数を増やすことでタイムアウトの時間を長くすることができます.

設定を変更する場合には下記のキーに TcpMaxDataRetransmissions という値を追加します.値の型は REG_DWORD で追加します.デフォルトでは値が無かったので追加が必要です.値の変更を行った場合は有効化するために再起動が必要です.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters

Wireshark でパケットのキャプチャ

Wireshark はほとんど使ったことがないのですが,試しにインストールしてパケットをキャプチャしてみました.下記の画像が実際にエラーが起こった時の通信パケットのキャプチャをしたものです.

wireshark_tcp_retransmission

No.1-3 で 3 ウェイ・ハンドシェイクを行った後,No.4 でアプリから計測器側へコマンドを送っています.No.4 への応答が計測器側から無いため,その後 No.5-9 の 5 回に渡ってデータの再送を行っています.この再送を TCP Retransmission といい No.4 と同一内容のものを再送信しています.

No.12 で 6 回目の再送が行われているのですが原因がわかりません.また再送完了時点と recv 関数にてエラーが発生する時間に差異がある理由などよくわからない点も多いのですが,大まかな流れはわかりました.

参考