Page 1 of 1
让 WinHttp.WaitForResponse() 超时等待超过 30 秒
Posted: 08 Aug 2015, 23:18
by tmplinshi
默认情况下,WinHttp.WaitForResponse() 最多只能等待 30 秒,也就是说...
- WinHttp.WaitForResponse() ; 最多等待 30 秒,而不是无限期等待。
- WinHttp.WaitForResponse(60) ; 最多等待 30 秒,而不是 60 秒。
要让 WinHttp.WaitForResponse() 超时等待超过 30 秒,需要先调用
WinHttp.SetTimeouts(解析超时, 连接超时, 发送超时, 接收超时)
参数的超时单位是毫秒。比如把超时等待修改为 120 秒:
WinHttp.SetTimeouts(0, 60000, 30000, 120000)
前面三个值 0, 60000, 30000 是默认值。更多详细说明见
IWinHttpRequest::SetTimeouts method。
Code: Select all
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.Open("GET", URL, true)
whr.SetTimeouts(0, 60000, 30000, 120000)
whr.Send()
whr.WaitForResponse(90)
Re: 让 WinHttp.WaitForResponse() 超时等待超过 30 秒
Posted: 12 Nov 2021, 01:16
by tuzi
通过分析使用不同参数组合,访问连接不稳定及完全无法连接的网站而得出的日志,可以得到以下结论。WaitForResponse 就像是所有超时的总和 SetTimeouts 则是总和中的每个子项。
超时既可能因为总和,也可能因为某个子项,还可能因为一个原因未知的,时间总是固定为21秒的条件触发。
所以综合来看,设置超时参数时最好将 解析超时设为0(避免内存溢出) 然后将 连接超时、发送超时、接收超时、总超时 都设置为一样的。
这样当超时时间小于21秒时,一定会以设置的超时为准。
而当超时时间大于21秒时,则会随机的在21秒或设定值时返回。
以下是测试代码。
Code: Select all
loop, 40
{
st:=A_TickCount
ComObjError(0)
wr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
; 解析超时=0 连接超时=60000 发送超时=30000 接收超时=11000
wr.SetTimeouts(0, 60000, 30000, 11000)
wr.Open("GET", "https://raw.githubusercontent.com/telppa/PaddleOCR-AutoHotkey/main/PaddleOCR/Dll/opencv_world452.dll", true)
; wr.Open("GET", "https://www.google.com", true)
wr.Send()
; 总超时=25000
wr.WaitForResponse(25)
FileAppend, % A_TickCount-st "|" wr.Status() "`n", 超时.log
}
ExitApp
以下是不同参数,访问不同网址的超时日志。
Code: Select all
访问 github.com 访问 google.com
参数 0 60 30 11 25 0 8 12 16 4 0 8 12 16 25 参数 0 60 30 11 25 0 8 12 16 4 0 8 12 16 25
-----------------------------------------------------------------------------------------------------------------------
25063|200 4015|200 20015| 25047| 4047| 8016|
25031|200 4016| 8000| 25015| 4015| 8000|
17922| 4047| 19797| 25032| 4016| 8000|
21047| 4015| 8203| 25015| 4016| 8000|
21047| 4047| 8000| 25016| 4015| 8000|
21046| 4016| 25016|200 25016| 4016| 8000|
25032|200 4016| 10984| 25015| 4016| 8015|
21047| 4015| 8000| 21047| 4015| 7985|
25015|200 4016| 8000| 25016| 4016| 8000|
25016|200 4015| 8000| 25015| 4015| 8000|
25062|200 4016| 8000| 25016| 4016| 8000|
11688| 4016| 8000| 25062| 4016| 8000|
12015| 4015| 8000| 25016| 4015| 8000|
21047| 4016| 8000| 25031| 4016| 8000|
21032| 4016| 8000| 25016| 4016| 8000|
21031| 4015| 8000| 25047| 4015| 8000|
21031| 4016| 8000| 25047| 4016| 8000|
21047| 4015| 8000| 25015| 4015| 8000|
21031| 4016| 8000| 25016| 4016| 8000|
21047| 4016| 20000| 25016| 4016| 8000|
21016| 4047| 20000| 25015| 4015| 8000|
25015|200 4015| 8000| 25016| 4016| 8000|
10703| 4016| 8000| 25015| 4016| 8000|
25032|200 4015| 8000| 25016| 4015| 8000|
10968| 4016| 8000| 25016| 4016| 8000|
21047| 4016| 20000| 25015| 4015| 8000|
21032| 4015| 8000| 25016| 4016| 8000|
21062| 4016| 8000| 25016| 4016| 8000|
21047| 4016| 8000| 25015| 4015| 8000|
21031| 4015| 8000| 25016| 4016| 8000|
21047| 4016| 8000| 25015| 4016| 8000|
21719| 4015| 8000| 21016| 4015| 8000|
21047| 4016| 8000| 25016| 4016| 8000|
14953| 4016| 8000| 25015| 4015| 8000|
12000| 4015| 8000| 21032| 4016| 8000|
21031| 4016| 8000| 21046| 4016| 8000|
21047| 4016| 8000| 21047| 4015| 8000|
21047| 4015|200 8000| 21032| 4016| 8000|
21015| 4016| 8000| 25031| 4016| 8000|
21032| 4015| 8000| 25015| 4015| 8000|
Re: 让 WinHttp.WaitForResponse() 超时等待超过 30 秒
Posted: 21 Nov 2022, 22:05
by zhang
感谢分享,解决了我的问题,如果要下载大文件,WaitForResponse通常都会超时,另外给出用WinHttp下载二进制流并存储为文件的方法,以防有人需要
本例子仅作示例,不可直接运行,若要运行,请手动替换GET请求的网址
Code: Select all
;网址:="https://"
whr.Open("GET",网址,true)
;如果是大文件,文件下载时间会比较长,要增加Response的等待时间
whr.SetTimeouts(0, 60000, 30000, 120000)
whr.SetRequestHeader("Authorization",token)
whr.Send()
whr.WaitForResponse(210)
;如果下载的文件是二进制流,那么响应头会附带Content-Type: application/octet-stream;charset=UTF-8
tmp:=whr.GetResponseHeader("Content-Type")
if !instr(tmp,"octet-stream")
{
msgbox 请求的格式不正确,数据不是二进制流
exitapp
}
;如果下载的内容是文件,那么通常响应头会附带Content-disposition: attachment; filename=<文件名>.<后缀名>
tmp:=whr.GetResponseHeader("Content-disposition")
if !instr(tmp,"filename")
{
msgbox 请求的格式不正确,当前请求返回的不是文件类型
exitapp
}
文件名:=Strsplit(tmp,"filename")[2]
;使用adodb.stream对象处理二进制流
stm:=ComObjCreate("adodb.stream")
stm.Type:=1 ;以二进制模式读取
stm.open()
stm.Write(whr.ResponseBody) ;这里要使用ResponseBody而不是ResponseText
;指定文件保存位置
stm.SaveToFile("D:\" . 文件名,2)
stm.flush()
stm.Close()