基础连接已关闭;但在浏览器中有效
The underlying connection was closed; but works in browsers
我在 wifi 芯片上有一个简单的网络服务器 运行(esp8266,在 nodeMCU 上用 LUA、运行 编写)。当我在任何浏览器中查询网站时,我都会得到预期的响应并显示在浏览器中(大约 45 个字符长)。当我在 C# 或 powershell 中查询它时,我得到:
"The underlying connection was closed: The connection was closed
unexpectedly."
我尝试了很多论坛建议的许多选项,但 none 似乎有效。
是否有任何方法可以像 IE 或 Chrome 一样发出 Web 请求?我不确定浏览器在内部执行了哪些额外步骤,以便他们能够毫无问题地获得响应?为什么这是 .NET 中的问题?
我的脚本如下。我正在考虑只使用 c# 来启动 PhantomJS(无头浏览器),然后使用 javascript 告诉它打开网站,然后传回响应。或者,使用套接字打开连接并以这种方式进行,而不是依赖 .NET 包装器。
# Set the useUnsafeHeaderParsing property to true
$netAssembly = [Reflection.Assembly]::GetAssembly([System.Net.Configuration.SettingsSection])
$bindingFlags = [Reflection.BindingFlags] "Static,GetProperty,NonPublic"
$settingsType = $netAssembly.GetType("System.Net.Configuration.SettingsSectionInternal")
$instance = $settingsType.InvokeMember("Section", $bindingFlags, $null, $null, @())
if($instance)
{
$bindingFlags = "NonPublic","Instance"
$useUnsafeHeaderParsingField = $settingsType.GetField("useUnsafeHeaderParsing", $bindingFlags)
if($useUnsafeHeaderParsingField)
{
$useUnsafeHeaderParsingField.SetValue($instance, $true)
}
}
# Try setting the certificate policy to a custom child class that always returns true
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
# Try setting other attributes on the ServicePointManager class
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls -bxor [System.Net.SecurityProtocolType]::Ssl3
[System.Net.ServicePointManager]::Expect100Continue = $false;
# Initiate the web request
$r = [System.Net.WebRequest]::Create("http://192.168.1.7/GetStatusAsJson")
# Try long timeouts, with KeepAlive set to false; Also try giving it a user agent string etc.
$r.Timeout = 5000
$r.ReadWriteTimeout = 5000
$r.KeepAlive = $false
$r.Method = "GET"
$r.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36";
$r.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
$resp = $r.GetResponse()
我最终使用了 MSXML2.XMLHTTP.3.0 和 vbscript,并从 powershell 执行了 vbscript。
on error resume next
Dim oXMLHTTP
Dim oStream
Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP.3.0")
oXMLHTTP.Open "GET", WScript.Arguments.Item(2) & "/OpenDoor", False
oXMLHTTP.Send
If oXMLHTTP.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write oXMLHTTP.responseBody
oStream.SaveToFile WScript.Arguments.Item(0) & "\OpenDoor.html"
oStream.Close
End If
我在 wifi 芯片上有一个简单的网络服务器 运行(esp8266,在 nodeMCU 上用 LUA、运行 编写)。当我在任何浏览器中查询网站时,我都会得到预期的响应并显示在浏览器中(大约 45 个字符长)。当我在 C# 或 powershell 中查询它时,我得到:
"The underlying connection was closed: The connection was closed unexpectedly."
我尝试了很多论坛建议的许多选项,但 none 似乎有效。
是否有任何方法可以像 IE 或 Chrome 一样发出 Web 请求?我不确定浏览器在内部执行了哪些额外步骤,以便他们能够毫无问题地获得响应?为什么这是 .NET 中的问题?
我的脚本如下。我正在考虑只使用 c# 来启动 PhantomJS(无头浏览器),然后使用 javascript 告诉它打开网站,然后传回响应。或者,使用套接字打开连接并以这种方式进行,而不是依赖 .NET 包装器。
# Set the useUnsafeHeaderParsing property to true
$netAssembly = [Reflection.Assembly]::GetAssembly([System.Net.Configuration.SettingsSection])
$bindingFlags = [Reflection.BindingFlags] "Static,GetProperty,NonPublic"
$settingsType = $netAssembly.GetType("System.Net.Configuration.SettingsSectionInternal")
$instance = $settingsType.InvokeMember("Section", $bindingFlags, $null, $null, @())
if($instance)
{
$bindingFlags = "NonPublic","Instance"
$useUnsafeHeaderParsingField = $settingsType.GetField("useUnsafeHeaderParsing", $bindingFlags)
if($useUnsafeHeaderParsingField)
{
$useUnsafeHeaderParsingField.SetValue($instance, $true)
}
}
# Try setting the certificate policy to a custom child class that always returns true
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
# Try setting other attributes on the ServicePointManager class
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls -bxor [System.Net.SecurityProtocolType]::Ssl3
[System.Net.ServicePointManager]::Expect100Continue = $false;
# Initiate the web request
$r = [System.Net.WebRequest]::Create("http://192.168.1.7/GetStatusAsJson")
# Try long timeouts, with KeepAlive set to false; Also try giving it a user agent string etc.
$r.Timeout = 5000
$r.ReadWriteTimeout = 5000
$r.KeepAlive = $false
$r.Method = "GET"
$r.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36";
$r.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
$resp = $r.GetResponse()
我最终使用了 MSXML2.XMLHTTP.3.0 和 vbscript,并从 powershell 执行了 vbscript。
on error resume next
Dim oXMLHTTP
Dim oStream
Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP.3.0")
oXMLHTTP.Open "GET", WScript.Arguments.Item(2) & "/OpenDoor", False
oXMLHTTP.Send
If oXMLHTTP.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write oXMLHTTP.responseBody
oStream.SaveToFile WScript.Arguments.Item(0) & "\OpenDoor.html"
oStream.Close
End If