从 vb.net 中的硬件设备读取远程 XML 文件(违反协议)
Read Remote XML file from Hardware Device in vb.net (Protocol Violation)
我有一个内置小型网络服务器的硬件设备。我不控制 Web 服务器的工作方式或编程方式。当您请求它时,它会发回一个小的 XML 文件,问题是服务器不会发回任何 header 信息。
以下是我尝试连接到它的方法。 (我什至将设备放在自己的静态 ip 上供您测试 - 包含在下面的代码片段中)。
Dim request As HttpWebRequest = HttpWebRequest.Create("http://96.39.92.3:81/state.xml")
request.Method = WebRequestMethods.Http.Get
' I Have added the following two lines to test, they do not help alone or together.
' I also added: <httpWebRequest useUnsafeHeaderParsing="true" /> to the config file.
request.ProtocolVersion = HttpVersion.Version10
request.ServicePoint.Expect100Continue = False
Dim oResponse As HttpWebResponse = request.GetResponse()
Dim reader As New StreamReader(oResponse.GetResponseStream())
Dim tmp As String = reader.ReadToEnd()
oResponse.Close()
If oResponse.StatusCode = "200" Then
MsgBox(tmp)
Else
Throw New ApplicationException("Error Occurred, Code: " & oResponse.StatusCode)
End If
我也尝试过使用 XmlTextReader 得到相同的结果。
感谢您的帮助。
编辑:Fiddler 响应(使用 Chrome 请求文档)
RAW REQUEST:
GET http://96.39.92.3:81/state.xml HTTP/1.1
Host: 96.39.92.3:81
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
RAW RESPONSE:
HTTP/1.0 200 This buggy server did not return headers
<?xml version="1.0" encoding="utf-8"?>
<datavalues>
<relaystate>1</relaystate>
<inputstate>0</inputstate>
<rebootstate>0</rebootstate>
<totalreboots>0</totalreboots>
</datavalues>
打开 Fiddler 后,上面的 httpwebrequest 就可以工作了。 Fiddler 在到达 .net 应用程序之前必须重新添加 headers。
编辑 2:调整了请求的 Header 值。这使 icepickles tcpclient 为我工作。需要 cookie 值。
WriteTextToStream(stream, tcpClient, "GET /state.xml?relayState=1 HTTP/1.0" & ControlChars.CrLf & _
" Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*" & ControlChars.CrLf & _
"Referer: " & ControlChars.CrLf & "Accept -Language : en -gb" & ControlChars.CrLf & _
"Content-Type: application/x-www-form-urlencoded" & ControlChars.CrLf & _
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6" & ControlChars.CrLf & _
"Host: 192.168.1.232" & ControlChars.CrLf & _
"Connection: Keep -Alive" & ControlChars.CrLf & ControlChars.CrLf & _
"Cookie:")
我重新启动了这个 post,根据评论,原来的回复应该还在编辑链中,以防有人 needs/wants 它。
我们的想法是,不使用内置了所有额外检查的 HttpWebRequest,您只需使用 TcpClient 连接到您的服务器,或者由于您的额外问题,请尝试使用基本套接字连接到服务器,并手动请求您的数据(忽略您没有得到 headers 的事实,只是响应中的文件)
以下内容在我的计算机上运行以请求 url,我确定它也适用于以前的 TcpClient(请参阅编辑),但在这种情况下,我只使用了 System.Net.Sockets.Socket 代替。
之前版本的错误实际上是我在字符串文字中使用了 C# \r\n 而不是 VB.net VbCrLf,我的错误 ;)
Imports System.Net.Sockets
Imports System.Net
Imports System.Text
Module Module1
Sub WriteTextToStream(ByRef stream As NetworkStream, text As String)
Dim buffer As Byte() = System.Text.Encoding.ASCII.GetBytes(text)
stream.Write(buffer, 0, buffer.Length)
End Sub
Function CreateHeaders(ParamArray headers() As KeyValuePair(Of String, String)) As String
Dim message As New StringBuilder()
If headers IsNot Nothing Then
For Each kvp In headers
message.AppendLine(kvp.Key & ": " & kvp.Value)
Next
End If
Return message.ToString()
End Function
Function DownloadSocketClient(server As String, port As Integer, path As String, host As String) As String
Dim hostEntry = Dns.GetHostEntry(server)
Dim ipEndPoint As New IPEndPoint(hostEntry.AddressList(0), port)
Dim textResponse As String = String.Empty
Using tcpClient As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
tcpClient.Connect(ipEndPoint)
Dim networkHost As String = host & ":" & port
Dim headerMessage As String = CreateHeaders(
New KeyValuePair(Of String, String)("Host", networkHost)
)
' autoconnect
Using stream As NetworkStream = New NetworkStream(tcpClient)
' send request to server
WriteTextToStream(stream, String.Format("GET /{1} HTTP/1.1{3}{2}{3}", networkHost, path, headerMessage, Environment.NewLine))
'wait till data is available
While Not stream.DataAvailable
System.Threading.Thread.Sleep(1)
End While
' get the response from the networkstream
Dim requestSize As Integer = tcpClient.ReceiveBufferSize
Dim result As Integer
Dim readRequest(requestSize) As Byte
While stream.DataAvailable
result = stream.Read(readRequest, 0, requestSize)
textResponse &= System.Text.Encoding.UTF8.GetString(readRequest, 0, result)
End While
End Using
End Using
Return textResponse
End Function
Sub Main()
Dim fileContent As String = DownloadSocketClient("Whosebug.server.textconnects.com", 81, "state.xml", "Whosebug.server.textconnects.com")
Console.WriteLine("Received file: " & vbCrLf & fileContent)
Console.ReadLine()
End Sub
End Module
我有一个内置小型网络服务器的硬件设备。我不控制 Web 服务器的工作方式或编程方式。当您请求它时,它会发回一个小的 XML 文件,问题是服务器不会发回任何 header 信息。
以下是我尝试连接到它的方法。 (我什至将设备放在自己的静态 ip 上供您测试 - 包含在下面的代码片段中)。
Dim request As HttpWebRequest = HttpWebRequest.Create("http://96.39.92.3:81/state.xml")
request.Method = WebRequestMethods.Http.Get
' I Have added the following two lines to test, they do not help alone or together.
' I also added: <httpWebRequest useUnsafeHeaderParsing="true" /> to the config file.
request.ProtocolVersion = HttpVersion.Version10
request.ServicePoint.Expect100Continue = False
Dim oResponse As HttpWebResponse = request.GetResponse()
Dim reader As New StreamReader(oResponse.GetResponseStream())
Dim tmp As String = reader.ReadToEnd()
oResponse.Close()
If oResponse.StatusCode = "200" Then
MsgBox(tmp)
Else
Throw New ApplicationException("Error Occurred, Code: " & oResponse.StatusCode)
End If
我也尝试过使用 XmlTextReader 得到相同的结果。
感谢您的帮助。
编辑:Fiddler 响应(使用 Chrome 请求文档)
RAW REQUEST:
GET http://96.39.92.3:81/state.xml HTTP/1.1
Host: 96.39.92.3:81
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
RAW RESPONSE:
HTTP/1.0 200 This buggy server did not return headers
<?xml version="1.0" encoding="utf-8"?>
<datavalues>
<relaystate>1</relaystate>
<inputstate>0</inputstate>
<rebootstate>0</rebootstate>
<totalreboots>0</totalreboots>
</datavalues>
打开 Fiddler 后,上面的 httpwebrequest 就可以工作了。 Fiddler 在到达 .net 应用程序之前必须重新添加 headers。
编辑 2:调整了请求的 Header 值。这使 icepickles tcpclient 为我工作。需要 cookie 值。
WriteTextToStream(stream, tcpClient, "GET /state.xml?relayState=1 HTTP/1.0" & ControlChars.CrLf & _
" Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*" & ControlChars.CrLf & _
"Referer: " & ControlChars.CrLf & "Accept -Language : en -gb" & ControlChars.CrLf & _
"Content-Type: application/x-www-form-urlencoded" & ControlChars.CrLf & _
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6" & ControlChars.CrLf & _
"Host: 192.168.1.232" & ControlChars.CrLf & _
"Connection: Keep -Alive" & ControlChars.CrLf & ControlChars.CrLf & _
"Cookie:")
我重新启动了这个 post,根据评论,原来的回复应该还在编辑链中,以防有人 needs/wants 它。
我们的想法是,不使用内置了所有额外检查的 HttpWebRequest,您只需使用 TcpClient 连接到您的服务器,或者由于您的额外问题,请尝试使用基本套接字连接到服务器,并手动请求您的数据(忽略您没有得到 headers 的事实,只是响应中的文件)
以下内容在我的计算机上运行以请求 url,我确定它也适用于以前的 TcpClient(请参阅编辑),但在这种情况下,我只使用了 System.Net.Sockets.Socket 代替。
之前版本的错误实际上是我在字符串文字中使用了 C# \r\n 而不是 VB.net VbCrLf,我的错误 ;)
Imports System.Net.Sockets
Imports System.Net
Imports System.Text
Module Module1
Sub WriteTextToStream(ByRef stream As NetworkStream, text As String)
Dim buffer As Byte() = System.Text.Encoding.ASCII.GetBytes(text)
stream.Write(buffer, 0, buffer.Length)
End Sub
Function CreateHeaders(ParamArray headers() As KeyValuePair(Of String, String)) As String
Dim message As New StringBuilder()
If headers IsNot Nothing Then
For Each kvp In headers
message.AppendLine(kvp.Key & ": " & kvp.Value)
Next
End If
Return message.ToString()
End Function
Function DownloadSocketClient(server As String, port As Integer, path As String, host As String) As String
Dim hostEntry = Dns.GetHostEntry(server)
Dim ipEndPoint As New IPEndPoint(hostEntry.AddressList(0), port)
Dim textResponse As String = String.Empty
Using tcpClient As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
tcpClient.Connect(ipEndPoint)
Dim networkHost As String = host & ":" & port
Dim headerMessage As String = CreateHeaders(
New KeyValuePair(Of String, String)("Host", networkHost)
)
' autoconnect
Using stream As NetworkStream = New NetworkStream(tcpClient)
' send request to server
WriteTextToStream(stream, String.Format("GET /{1} HTTP/1.1{3}{2}{3}", networkHost, path, headerMessage, Environment.NewLine))
'wait till data is available
While Not stream.DataAvailable
System.Threading.Thread.Sleep(1)
End While
' get the response from the networkstream
Dim requestSize As Integer = tcpClient.ReceiveBufferSize
Dim result As Integer
Dim readRequest(requestSize) As Byte
While stream.DataAvailable
result = stream.Read(readRequest, 0, requestSize)
textResponse &= System.Text.Encoding.UTF8.GetString(readRequest, 0, result)
End While
End Using
End Using
Return textResponse
End Function
Sub Main()
Dim fileContent As String = DownloadSocketClient("Whosebug.server.textconnects.com", 81, "state.xml", "Whosebug.server.textconnects.com")
Console.WriteLine("Received file: " & vbCrLf & fileContent)
Console.ReadLine()
End Sub
End Module