Tcp / Ip C#Bad Request / Missing Pakets

时间:2018-03-26 09:07:23

标签: c# sockets tcp ip

我目前正在使用内置嵌入式Linux Web服务器的测量设备,可以使用所谓的CGI - LAN接口进行控制。如果想要更改设备的设置,必须首先发送TCP / IP登录数据包,然后发送一个密钥代码来控制指定的功能或接收数据。

通过使用TCP / IP数据包工具,例如Paket Sender,一切正常。从端口80到192.168.0.2(PC)的192.168.0.1(设备)的登录数据包,带有ASCII文本的192.168.0.2(PC)(这些是标准密码和登录名,所以我不会模糊这一点):

GET /cgi-bin/login.cgi?username=long&password=nga HTTP/1.0 \n \n

从设备成功接收并确认,如wireshark协议中所示: Wireshark Screenshot

但与Microsoft提供的Standard C# TCP/IP Client相同的请求会返回错误请求错误消息。有点C#不发送[FIN,ACK]数据包,如#34;数据包发送者"。 Microsoft修改后的代码如下:

// Data buffer for incoming data.  
        byte[] bytes = new byte[1024];

        // Connect to a remote device.  
        try
        {
            // Establish the remote endpoint for the socket.  
            // This example uses port 11000 on the local computer.  
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 80);

            // Create a TCP/IP  socket.  
            Socket sender = new Socket(IPAddress.Parse("192.168.0.1").AddressFamily,
                SocketType.Stream, ProtocolType.Tcp);

            // Connect the socket to the remote endpoint. Catch any errors.  
            try
            {
                sender.Connect(remoteEP);

                Console.WriteLine("Socket connected to {0}",
                    sender.RemoteEndPoint.ToString());

                // Encode the data string into a byte array.  
                byte[] msg = Encoding.ASCII.GetBytes("GET /cgi-bin/login.cgi?username=long&password=nga HTTP/1.0 \n \n");

                // Send the data through the socket.  
                int bytesSent = sender.Send(msg);

                // Receive the response from the remote device.  
                int bytesRec = sender.Receive(bytes);
                Console.WriteLine("Echoed test = {0}",
                    Encoding.ASCII.GetString(bytes, 0, bytesRec));

                // Release the socket.  
                sender.Shutdown(SocketShutdown.Both);
                sender.Close();

            }
            catch (ArgumentNullException ane)
            {
                Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
            }
            catch (SocketException se)
            {
                Console.WriteLine("SocketException : {0}", se.ToString());
            }
            catch (Exception e)
            {
                Console.WriteLine("Unexpected exception : {0}", e.ToString());
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

此代码段的输出:

Socket connected to 192.168.0.1:80
Echoed test = HTTP/1.0 408 Request Timeout
Content-type: text/html
Date: Mon, 26 Mar 2018 16:41:34 GMT
Connection: close

<HTML><HEAD><TITLE>408 Request Timeout</TITLE></HEAD>
<BODY><H1>408 Request Timeout</H1>
No request appeared within 60 seconds
</BODY></HTML>

Wireshark Screenshot此次沟通。

好吧,我不知道为什么C#没有发送[FIN,ACK]消息。也许有人经历过同样的事情?或者有一个简单的解释?也许我错过了TCP / IP套接字中的一个选项?如果有帮助,我还可以提供Wireshark协议文件。

1 个答案:

答案 0 :(得分:1)

我猜服务器要求发送方在发送响应之前发送FIN / ACK ,是吗? FIN意味着关闭该(定向)流,所以如果问题确实是缺少的FIN,我猜测发送请求之后你需要的是但是< em>在听取响应之前,添加:

sender.Shutdown(SocketShutdown.Send);

应该FIN出站连接。

但是,请参阅Dirk对该问题的评论;它可能只是你没有正确形成一个完整的请求,而且FIN目前让它间接工作

请注意, 也可能想要设置sender.NoDelay = true;,但这应该是无关的。