/// <summary>
        /// レスポンス文字列をパースする
        /// </summary>
        public static SSTPResponse Parse(string message)
        {
            var headerPattern = new Regex(Message.HeaderPattern);

            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            // メッセージを改行で分割
            var lines = message.Split(new[] { "\r\n" }, StringSplitOptions.None);

            // 1行目のステータス行が正しければ有効なSSTPレスポンス
            var matched = Regex.Match(lines[0], @"^(SSTP/[0-9.]+)\s+(\d{1,7})(?:\s+(.+))?"); // 仕様上ステータスコードの桁数には記載がないため、一応7桁まで受け付ける

            if (matched.Success)
            {
                var    version     = matched.Groups[1].Value;
                var    statusCode  = int.Parse(matched.Groups[2].Value);
                string explanation = null;
                if (matched.Groups[3].Success)
                {
                    explanation = matched.Groups[3].Value;
                }

                var res = new SSTPResponse();
                res.Version           = version;
                res.StatusCode        = statusCode;
                res.StatusExplanation = explanation;

                // 2行目以降の行をパース
                var additionalLines = new List <string>();
                for (var i = 1; i < lines.Length; i++)
                {
                    var line = lines[i];

                    // 空行は読み飛ばす
                    if (line == "")
                    {
                        continue;
                    }

                    // 追加情報として格納
                    additionalLines.Add(line);
                }

                // 追加情報があればセット
                if (additionalLines.Any())
                {
                    res.AdditionalData = string.Join("\r\n", additionalLines);
                }

                return(res);
            }
            else
            {
                throw new BadRequestException(string.Format("有効なSSTPレスポンスではありません。 (コマンド行: {1})", lines[0]));
            }
        }
        /// <summary>
        /// SSTPリクエストを送信し、レスポンスを得る
        /// </summary>
        /// <param name="req">リクエストオブジェクト</param>
        /// <remarks>
        /// khskさんの作成されたソースを参考にしています。
        /// https://qiita.com/khsk/items/177741a6c573790a9379
        /// </remarks>
        /// <returns>成功した場合はResponseオブジェクト、失敗した場合はnull</returns>
        public virtual SSTPResponse SendRequest(SSTPRequest req)
        {
            // Charset未指定のリクエストには対応しない
            if (req.Encoding == null)
            {
                new ArgumentException(string.Format("{0} でSSTPリクエストを送信する場合は、リクエストに有効なCharsetを指定する必要があります。", MethodBase.GetCurrentMethod().Name));
            }

            if (DebugLogging)
            {
                Debug.WriteLine("[SSTP Request]");
                Debug.WriteLine(req.ToString());
            }

            var data = req.Encoding.GetBytes(req.ToString());

            using (var client = new TcpClient(ToHost, ToPort))
            {
                using (var ns = client.GetStream())
                {
                    ns.ReadTimeout  = 10 * 1000; // 読み込みタイムアウト10秒
                    ns.WriteTimeout = 10 * 1000; // 書き込みタイムアウト10秒

                    // リクエストを送信する
                    ns.Write(data, 0, data.Length); // リクエスト

                    //サーバーから送られたデータを受信する
                    using (var ms = new System.IO.MemoryStream())
                    {
                        var resBytes = new byte[256];
                        var resSize  = 0;
                        do
                        {
                            //データの一部を受信する
                            resSize = ns.Read(resBytes, 0, resBytes.Length);

                            //Readが0を返した時はサーバーが切断したと判断
                            if (resSize == 0)
                            {
                                break;
                            }

                            //受信したデータを蓄積する
                            ms.Write(resBytes, 0, resSize);

                            //まだ読み取れるデータがあるか、データの最後が\nでない時は、受信を続ける
                        } while (ns.DataAvailable || resBytes[resSize - 1] != '\n');

                        // 受信したデータを文字列に変換
                        var resMsg = req.Encoding.GetString(ms.GetBuffer(), 0, (int)ms.Length);
                        // 末尾の\0, \nを削除
                        resMsg = resMsg.TrimEnd('\0').TrimEnd();

                        if (DebugLogging)
                        {
                            Debug.WriteLine("[SSTP Response]");
                            Debug.WriteLine(resMsg);
                        }

                        return(SSTPResponse.Parse(resMsg));
                    }
                }
            }
        }