C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[13]: WebClientを使って定期的に実行したい


(過去ログ 132 を表示中)

[トピック内 17 記事 (1 - 17 表示)]  << 0 >>

■78112 / inTopicNo.1)  WebClientを使って定期的に実行したい
  
□投稿者/ yabu (1回)-(2015/12/15(Tue) 19:20:57)

分類:[VB.NET/VB2005 以降] 

はじめまして
vb 2008 express を使用してテストプログラムを作成しています。
HTTPのPOSTメソッドを使用してタイマーコントロールを利用して
定期的にデータを取り出したいと考えています。
まず手始めにボタンを押すたびに実行するように作成してみました。

  Dim p As String
  p = "POSTしたいデータ"
  Dim w As Object
  w = New Net.WebClient()
  w.Headers.Add("Content-Type", "application/xml")
  Dim d As Byte() = System.Text.Encoding.ASCII.GetBytes(p)
  w.Credentials = New NetworkCredential("ID", "PASSWD")
  Dim r As Byte() = w.UploadData("http://localhost:8000/api?cls=001", "POST", d)
  MsgBox(System.Text.Encoding.ASCII.GetString(r))

一度目は期待した動作をするのですが、再度ボタンを押すと

WebExceptionはハンドルされませんでした。
基礎になる接続が閉じられました:維持される必要があった接続が、
     サーバーによって切断されました

とエラーとなってしまいます。
いろいろと調べたのですが、まだ勉強不足で調べきれません。
ボタンを押すたびに Msgbox にデータが表示されるようにしたいのですが、
どなたか解決策をご教示いただけないでしょうか。

引用返信 編集キー/
■78115 / inTopicNo.2)  Re[1]: WebClientを使って定期的に実行したい
□投稿者/ Hongliang (385回)-(2015/12/15(Tue) 20:08:48)
Using w As New Net.WebClient()
    ...
    MsgBox(System.Text.Encoding.ASCII.GetString(r))
End Using
としてみたらどうでしょうか?
// なぜwをAs Objectにしてるんでしょうか…。

引用返信 編集キー/
■78121 / inTopicNo.3)  Re[2]: WebClientを使って定期的に実行したい
□投稿者/ yabu (2回)-(2015/12/16(Wed) 11:55:08)
ご回答ありがとうございます。

  Dim p As String
  p = "POSTしたいデータ"
  Using w As New Net.WebClient()
      w.Headers.Add("Content-Type", "application/xml")
      Dim d As Byte() = System.Text.Encoding.ASCII.GetBytes(p)
      w.Credentials = New NetworkCredential("ID", "PASSWD")
      Dim r As Byte() = w.UploadData("http://localhost:8000/api?cls=001", "POST", d)
      MsgBox(System.Text.Encoding.ASCII.GetString(r))
 End Using

と変更してやってみましたが、やはり UploadData のところで
同じエラーが発生します。
また、数分時間をおいて再度ボタンを押してみると違うエラー
  WebExceptionはハンドルされませんでした
   要求は中止されました:要求がキャンセルされました
とでます。

すみませんが引き続きお願い致します。

> // なぜwをAs Objectにしてるんでしょうか…。
質問用に一部書き換えしていました。
実際には Dim w As New Net.WebClient() を使用しておりました。

Using というものがあること参考になりました。ありがとうございます。

引用返信 編集キー/
■78122 / inTopicNo.4)  Re[3]: WebClientを使って定期的に実行したい
□投稿者/ 魔界の仮面弁士 (604回)-(2015/12/16(Wed) 15:04:08)
No78121 (yabu さん) に返信
> Dim r As Byte() = w.UploadData("http://localhost:8000/api?cls=001", "POST", d)


当初は、POST 要求が受け入れない設定になっているのかとも思いましたが、
切断されてしまっているということは、アンチウィルスソフトウェア等で
ブロックされているとか、あるいはローカルプロキシの問題であるなど、
プログラム以外の環境要因である可能性が思い浮かびます。


Web サーバーが IIS なのか Cassini なのか分かりませんが、
サーバー側のアクセスログには、どのように記録されていますか?
引用返信 編集キー/
■78125 / inTopicNo.5)  Re[4]: WebClientを使って定期的に実行したい
□投稿者/ yabu (3回)-(2015/12/16(Wed) 16:50:35)
ご回答ありがとうございます。

Webサーバーについてはubuntuで動作しておりAPI仕様のみ公開されており内部のログは
確認することができず困っております。

ただ、下記のようなボタン1のクリックで実行するようにしており
  Private Sub Button1_Click( ... )
    ...
  End Sub
フォームが表示されて1回目のクリックでは正常に動作(レスポンスが帰ってきます。)します。
少し間を置いて再度ボタン1を押すとエラーが発生するのです。
また、一度デバッグを終了し、再度動かすと1回目は正常に動作します。

プロキシやアンチウイルスソフトも考えたのですが、
初回は影響なし、2回目以降悪さをするということは考えづらいかと思いました。

引き続きご意見をよろしくお願い致します。
引用返信 編集キー/
■78162 / inTopicNo.6)  Re[5]: WebClientを使って定期的に実行したい
□投稿者/ WebSurfer (742回)-(2015/12/18(Fri) 12:12:28)
No78125 (yabu さん) に返信

> Webサーバーについてはubuntuで動作しておりAPI仕様のみ公開されており内部のログは
> 確認することができず困っております。

原因は Web サーバー側にあるということはないのですか?

例えば FTP サーバで、すでにあるファイルへの上書きがエラーとなる
ということは良くあるそうですが、それと似たようなことが起こって
いるとか・・・

Web サーバーが質問者さんの管轄外でログなどは取得できないというこ
とらしいですが、せめてサーバーとのやり取りをキャプチャツールを使
って確認するということはできないのでしょうか?
引用返信 編集キー/
■78171 / inTopicNo.7)  Re[6]: WebClientを使って定期的に実行したい
□投稿者/ yabu (4回)-(2015/12/18(Fri) 14:34:46)
魔界の仮面弁士さん、WebSurferさんお二方よりWebサーバが原因ではないかとの
返信をいただきましたので、Fiddler4というツールを使ってみました。

結果、間に上記のキャプチャツールを挟むと問題なく動作します。
ただ、はずすと同様のエラーとなりました。

このような現象ご存じの方はいらっしゃるでしょうか。

また、いろいろと情報を探していたところウエイトをいれると動くとあったので
試してみました。今回のプログラムでは何カ所かに入れてみたのですが駄目だったので、
WebRequestとIO.Streamを使用したものを新たに作成し、サーバへのPOSTデータの書き込みと
サーバからのリプライ処理の間にウエイトを100ms程度入れると動くようになりました。
原因はわからないのですが、サーバとして使用しているプログラムの仕様みたいなものかもしれません。

とりあえず、動いてはいるので解決済みにさせていただきます。




解決済み
引用返信 編集キー/
■78172 / inTopicNo.8)  Re[7]: WebClientを使って定期的に実行したい
□投稿者/ WebSurfer (745回)-(2015/12/18(Fri) 15:28:21)
No78171 (yabu さん) に返信
> 魔界の仮面弁士さん、WebSurferさんお二方よりWebサーバが原因ではないかとの
> 返信をいただきましたので、Fiddler4というツールを使ってみました。
>
> 結果、間に上記のキャプチャツールを挟むと問題なく動作します。
> ただ、はずすと同様のエラーとなりました。
>
> このような現象ご存じの方はいらっしゃるでしょうか。

Fiddler はプロキシとしてクライアントのアプリと Web サーバーの間に入るので、
全くの想像ですが、それが入ることによりウエイトを入れたのと同じ効果があった
のではないかと思われます。

> WebRequestとIO.Streamを使用したものを新たに作成し、サーバへのPOSTデータの書き込みと
> サーバからのリプライ処理の間にウエイトを100ms程度入れると動くようになりました。

具体的にどのようにしたのかの情報を提供していただけませんか?
引用返信 編集キー/
■78174 / inTopicNo.9)  Re[8]: WebClientを使って定期的に実行したい
□投稿者/ yabu (5回)-(2015/12/18(Fri) 16:38:50)
VBはあまり詳しくないので不作法なコードかもしれません。

ソースはほぼ DOBON.NET さんのものを使用させていただきました。
データのPOST後とサーバからのリプライを処理する前にwaitを入れました。
原因は追及できていませんがとりあえず期待通りの動作をしております。
本当はWebClientを使ってやりたかったのですが...

--- 以下プログラムコードです ---

Dim dataBytes As Byte() = System.Text.Encoding.ASCII.GetBytes("POST DATA")

Dim req As System.Net.WebRequest = _
System.Net.WebRequest.Create("http://localhost:8000/api?class=1")
req.Method = "POST"
req.Credentials = New NetworkCredential("ID", "PASSWD")
req.ContentType = "appplication/xml"
req.ContentLength = dataBytes.Length

Dim reqStream As System.IO.Stream = req.GetRequestStream()
reqStream.Write(postDataBytes, 0, postDataBytes.Length)
reqStream.Close()

System.Threading.Thread.Sleep(100) '追加したウエイト

Using res As System.Net.WebResponse = req.GetResponse()
Dim resStream As System.IO.Stream = res.GetResponseStream()
Dim sr As New System.IO.StreamReader(resStream, enc)
Console.Writeln(sr.ReadToEnd)
sr.Close()
End Using
引用返信 編集キー/
■78178 / inTopicNo.10)  Re[9]: WebClientを使って定期的に実行したい
□投稿者/ WebSurfer (746回)-(2015/12/18(Fri) 22:21:11)
No78174 (yabu さん) に返信

情報提供をありがとうございました。

でも、そこで 100ms 待ったらうまく行くようになったというのが不思議です。
その前のコードで応答は帰ってきているはずなのですが・・・

先の話の「基礎になる接続が閉じられました」とか「要求は中止されました」
というのとも話が合わないような気がしますし。

あと、私の先のレスで、

> Fiddler はプロキシとしてクライアントのアプリと Web サーバーの間に入るので、

と書きましたけど、Fiddler ではキャプチャできなかったですね。すみません。
それなのに Fiddler を入れたら問題が出なくなったというのも不可解です。

WebClient も WebRequest もリクエストヘッダ に Except: 100-continue を
含めるのでそれの問題かもと思いましたが、そこで 100ms 待ったらうまく行
くのだとすると、それも考えにくいですし・・・

HTTP 100-continue とは
http://d.hatena.ne.jp/naga_sawa/20101114/1289709797

明日また考えて見ます。
引用返信 編集キー/
■78184 / inTopicNo.11)  Re[9]: WebClientを使って定期的に実行したい
□投稿者/ WebSurfer (747回)-(2015/12/20(Sun) 11:39:46)
No78174 (yabu さん) に返信

その場所で 100ms 待って何故うまく行くようになったかは依然として謎で、
問題が再現できる環境がないと原因は分かりそうもないです。

ほぼギブアップなのでお役に立てそうもないですが、先のレスの後で調べて
分かったことを書いておきます。

まず Fiddler でのキャプチャですが、Expect: 100-continue があるとデフ
ォルトで 350ms 待たされるそうです。詳しくは以下の記事を見てください。

.NET HttpWebRequests and Expect: 100-continue
https://blogs.msdn.microsoft.com/fiddler/2011/11/05/net-httpwebrequests-and-expect-100-continue/

自分でも同様なコードで Fiddler で見てみましたが、認証のステップでクレ
デンシャルを送るにも 350ms、認証後のステップでデータを送信するにも
350ms 待たされるのを確認しました。

先のレスで、「Fiddler ではキャプチャできなかったですね」と書きましたけ
ど localhost でなければキャプチャできます。質問者さんのコードには、

> System.Net.WebRequest.Create("http://localhost:8000/api?class=1")

と書いてありましたけど、実際は localhost ではないのでは? であれば、
350ms + 350ms 待たされているはずで、その影響があるのかもしれません。

この先は質問者さんの方で、問題が再現できる環境で調べていただかないと
原因は分からないと思います。その気があればやってみてください。例えば、

(1) 上で紹介した記事の最後の方に Fiddler を 350ms 待たないように設定
  する方法が書いてあるので、それで問題の時の要求 / 応答をキャプチャ
  してみる。

(2) Fiddler に替えて Wireshark を使ってみる。

(3) HttpWebRequest を Expect: 100-continue を出さないように設定して試
  してみる。設定方法は下記の記事参照:

How to disable the “Expect: 100 continue” header in HttpWebRequest for a single request?
http://stackoverflow.com/questions/14063327/how-to-disable-the-expect-100-continue-header-in-httpwebrequest-for-a-single

引用返信 編集キー/
■78185 / inTopicNo.12)  Re[10]: WebClientを使って定期的に実行したい
□投稿者/ 魔界の仮面弁士 (612回)-(2015/12/20(Sun) 19:01:22)
No78184 (WebSurfer さん) に返信
> 先のレスで、「Fiddler ではキャプチャできなかったですね」と書きましたけ
> ど localhost でなければキャプチャできます。

localhost を Fiddler でキャプチャする場合は、
localhost. のように、末尾にドットを含めるか、
マシン名での接続に変更することで対応できたと思います。

http://stackoverflow.com/questions/4647105/how-to-configure-fiddler-to-listen-to-localhost
http://docs.telerik.com/fiddler/configure-fiddler/tasks/MonitorLocalTraffic
引用返信 編集キー/
■78187 / inTopicNo.13)  Re[11]: WebClientを使って定期的に実行したい
□投稿者/ yabu (6回)-(2015/12/20(Sun) 19:59:23)
WebSurferさん、貴重な時間を割いていただいての調査ありがとうございます。
ご指摘の通り実際はlocalhostではなくIPアドレス指定しています。
Expect: 100-continueを頼りにその後調べてみました。
Fiddlerで問題なくキャプチャできていたので、Expect:100-continueを無効に設定してやってみましたが
駄目でした。ただここでkeep-aliveというものが初回のPOSTに含まれ、2回目のPOSTには含まれていない
ことがわかったので、無効にしてみると ウエイトもUsing句がなくても動作しました。

コードは後日(火曜日に)改めて書かせていただきます。
取りあえず報告です。
引用返信 編集キー/
■78190 / inTopicNo.14)  Re[11]: WebClientを使って定期的に実行したい
□投稿者/ WebSurfer (748回)-(2015/12/21(Mon) 12:52:14)
No78185 (魔界の仮面弁士 さん) に返信

> localhost を Fiddler でキャプチャする場合は、
> localhost. のように、末尾にドットを含めるか、
> マシン名での接続に変更することで対応できたと思います。

情報をありがとうございます。ドットを追加というのは初めて知りました。


#ご存知だろうとは思いますが、ひょっとして知らない人もいるかもしれないので
 追加情報など。

Fiddler で localhost がダメなのは WebClient とか HttpWebRequest の場合で、
ブラウザ(IE9+, Firefox, Chrome は確認済み)からアクセスすると localhost
でもキャプチャできます。

IE と .NET Framework(Fiddler は .NET ベースのアプリです)は localhost の
要求をプロキシを通して送らないようにハードコードされているそうで、プロキシ
である Fiddler も localhost トラフィックのキャプチャはできなかったのが、IE9
がリリースされて事情が変わったそうです。

WebClient とか HttpWebRequest の場合はそのあたりの事情が変わってないのかも
しれません。
引用返信 編集キー/
■78191 / inTopicNo.15)  Re[12]: WebClientを使って定期的に実行したい
□投稿者/ WebSurfer (749回)-(2015/12/21(Mon) 13:06:35)
No78187 (yabu さん) に返信

> Fiddlerで問題なくキャプチャできていたので、Expect:100-continueを無効に設定してやってみましたが
> 駄目でした。ただここでkeep-aliveというものが初回のPOSTに含まれ、2回目のPOSTには含まれていない
> ことがわかったので、無効にしてみると ウエイトもUsing句がなくても動作しました。

サーバーが HTTP/1.0 しか対応していないのでしょうか? そうでもなけれ
ば(HTTP/1.1 に対応していれば)Connection: Keep-Alive は関係ないはず
なのですか・・・

【HTTP】Keep Alive のメモ
https://www.softel.co.jp/blogs/tech/archives/2490

サーバーが HTTP/1.0 しか対応していなくて、Connection: Keep-Alive を付与
しないと要求のたびに TCP 接続を開くということであれば、その分時間がかか
るので、コードで 100ms ウェイトを入れたのと同じ効果があったのかも知れま
せん。

そのあたりもチェックしてみてください。
引用返信 編集キー/
■78213 / inTopicNo.16)  Re[12]: WebClientを使って定期的に実行したい
□投稿者/ yabu (7回)-(2015/12/22(Tue) 12:25:24)
WebSurferさん、魔界の仮面弁士さんいろいろと情報をいただきありがとうございます。

サーバからは HTTP/1.1 200 OK などが帰ってきているので 1.1 に対応していると思います。
Fidderでいろいろみていたのですが、リクエスト後の待ち時間をどこで見るのががよくわかりません。
Statisticsのところの以下のところで確認するのでしょうか。

ACTUAL PERFORMANCE
--------------
ClientConnected:	09:50:30.795
ClientBeginRequest:	09:50:40.374
GotRequestHeaders:	09:50:40.374
ClientDoneRequest:	09:50:40.374
Determine Gateway:	0ms
DNS Lookup: 		0ms
TCP/IP Connect:	0ms
HTTPS Handshake:	0ms
ServerConnected:	09:50:30.810
FiddlerBeginRequest:	09:50:40.374
ServerGotRequest:	09:50:40.374
ServerBeginResponse:	09:50:40.374
GotResponseHeaders:	09:50:40.374
ServerDoneResponse:	09:50:40.374
ClientBeginResponse:	09:50:40.374
ClientDoneResponse:	09:50:40.374



ちなみに以下がコードです。

req.KeepAlive = False を削除して
reqStream.Close()のあとにSystem.Threading.Thread.Sleep(1)をいれても
動きました。ほんの1msの待ち時間ですが、sleep関数呼び出しの待ち時間が影響しているのでしょうか。


Dim postDataBytes As Byte() = System.Text.Encoding.ASCII.GetBytes("POSTしたいXML文字列")
Dim req As HttpWebRequest = CType(WebRequest.Create("http://192.168.X.XXX:8000/api?cls=01"), HttpWebRequest)
req.Credentials = New NetworkCredential("ID", "PASSWD")
req.Method = "POST"
req.ContentType = "appplication/xml"
req.ContentLength = postDataBytes.Length
req.KeepAlive = False

Dim reqStream As Stream = req.GetRequestStream()
reqStream.Write(postDataBytes, 0, postDataBytes.Length)
reqStream.Close()

Dim res As WebResponse = req.GetResponse()
Dim resStream As Stream = res.GetResponseStream()
Dim enc As Text.Encoding = System.Text.Encoding.GetEncoding("UTF-8")
Dim sr As StreamReader = New StreamReader(resStream, enc)
Dim resData As String = sr.ReadToEnd
sr.Close()
resStream.Close()

引用返信 編集キー/
■78214 / inTopicNo.17)  Re[13]: WebClientを使って定期的に実行したい
□投稿者/ WebSurfer (750回)-(2015/12/22(Tue) 14:56:59)
No78213 (yabu さん) に返信

> サーバからは HTTP/1.1 200 OK などが帰ってきているので 1.1 に対応していると思います。

そのようですね。ClientConnected と ServerConnected が 10 秒ほど前ですから前回確立した
TCP 接続を利用している(即ちデフォルトで Keep-Alive 状態)と思います。

> Fidderでいろいろみていたのですが、リクエスト後の待ち時間をどこで見るのががよくわかりません。
> Statisticsのところの以下のところで確認するのでしょうか。

紹介した記事に書いてありますように "between ClientBeginRequest and ClientDoneRequest"
です。

で、質問者さんのデータを見ると待ち時間はゼロですね。もう何が起こっているのか当方で
は分からないです。ひょっとしたらウェイトとは関係ないかもしれませんね。

ともかく、うまく動いた時の要求 / 応答をキャプチャしても原因は分からないと思いますの
で、Fiddler を使うと問題が再現できないなら、Wrieshark など他のキャプチャツールを使っ
て調べてみるしかなさそうです。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -