从 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