通过GPRS和TCP丢弃数据包的HTTP请求

时间:2017-09-28 11:15:52

标签: c# rest sockets networking tcp

我正在为通过GPRS连接的生物识别指纹设备编写服务器。服务器从设备接收GET和POST请求,然后执行所需的操作。

通过POST请求,设备应该将一些额外的数据附加到请求中。

问题是,当我通过LAN将设备连接到服务器时,所有数据都很好。当我通过GPRS连接时,我的服务器无法接收请求正文。

HTTP Request Comparisons 在左边,当我通过LAN连接时......消息的主体被附加。在右边,通过GPRS,一切都保持不变,然而,没有身体。

Wireshark bad tcp 我通过局域网和GPRS连接运行Wireshark。这些数据包,当我向下钻取时,都有附着的身体,但在Wireshark上,通过GPRS,我得到上面的消息 - 乱序,RST,ACK和有时PSH,ACK。

Wireshark good tcp

与没有这些问题的LAN数据包形成对比。

这是我用来从TCPListener

中读取的代码
try
  {
    if (tcp == null)
    {
       this.tcp = new TcpListener(IPAddress.Parse(serverIP), port);
    }
    this.tcp.Start();
    listening = true;

    while (listening)
    {
        Socket mySocket = null;

        // Blocks until a client has connected to the server
        try
        {
           mySocket = this.tcp.AcceptSocket();
           Thread.Sleep(500);

           byte[] bReceive = new byte[1024 * 1024 * 2];
           mySocket.Receive(bReceive);

           Analysis(bReceive, mySocket);
        }
        catch(Exception ex)
        {
           MessageBox.Show(ex.Message);
        }
    }

   this.tcp.Stop();

这是我从他们的开发者那里得到的原始代码。我尝试过各种async,TcpClient和不同套接字选项的组合,比如KeepAlive和DontLinger,但似乎都没有解决这个问题。

除了手动捕获C#中的数据包以获取正文外,是否有可用于读取整个请求的C#类?

2 个答案:

答案 0 :(得分:2)

TCP是面向流的协议。每个人都知道,但很多开发人员在实现TCP接收器时都没有考虑到这一点。

当发送呼叫Send("ABCDEFG")和客户呼叫Receive(buffer)时,buffer可能包含"ABCDEFG""ABCD""A"或来自原始的任何子字符串以"A"开头的数据。 TCP是一个数据流,没有任何有关消息边界的信息。

需要在编译期间接收长度未知的消息的接收方(如HTTP请求)必须包含一个接收标头,解析它的逻辑,然后等待直到收到完整的消息。

但是你不需要自己实现它。 C#具有已包含此逻辑的类HttpServer。此外,还有支持REST的库。它正在重新发明轮子以实现REST服务器并从TcpListener和套接字开始。

答案 1 :(得分:0)

我最终使用以下链接中的代码将服务器实现为异步。这样我就可以实现逻辑来重新读取流,如果尚未到达流的末尾。我只是因为我的情况而改变了文件结束条件。

以下是该文章的链接:

https://docs.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-server-socket-example