c# Http服务器使用StreamSocketListener,选项"InputStreamOptions.

本文关键字:选项 quot InputStreamOptions StreamSocketListener Http 服务器 | 更新日期: 2023-09-27 18:10:29

首先我正在做一个Windows Universal应用项目。我使用StreamSocketListener创建了一个简单的tcp侦听器。数据来自一个连接到我本地网络的设备。该设备随机发送Http和Http/Xml报文。

我已经创建了套接字监听器,如下所示:
StreamSocketListener listener = new StreamSocketListener();
public async void HttpServer()
{
   listener.ConnectionReceived += (s, e) => ProcessRequestAsync(e.Socket);
   HostName hostName = new HostName("192.168.0.150");
   NetworkAdapter thisAdapter = hostName.IPInformation.NetworkAdapter;
   await listener.BindServiceNameAsync("5400", SocketProtectionLevel.PlainSocket, thisAdapter);
}

当数据可用时,这是回调函数:

private const uint BufferSize = 12000;
private async void ProcessRequestAsync(StreamSocket socket)
{
    StringBuilder request = new StringBuilder();
    using (IInputStream input = socket.InputStream)
    {             
        byte[] data = new byte[BufferSize];
        IBuffer buffer = data.AsBuffer();
        uint dataRead = BufferSize;
        while (dataRead == BufferSize)
        {
            await input.ReadAsync(buffer, BufferSize, InputStreamOptions.None);
            request.Append(Encoding.UTF8.GetString(data, 0, (Int32)buffer.Length));
            dataRead = buffer.Length;
         }
    String message = request.ToString();
    ExampleTextLabel.Text = message;
    ....
}

问题是:

我已经设置BufferSize = 12000。这是因为,到目前为止,我收到的最大数据长度低于11500。内容的长度是在HTML标题(content - length),但我不确定如何阅读标题前行:

await input.ReadAsync(buffer, BufferSize, InputStreamOptions.None);

当我使用InputStreamOptions选项时。没有,我收到的消息延迟一个包。换句话说,当设备发送数据包1时,它不会将其写入以下文本标签:

ExampleTextLabel.Text = message;

当数据包2到达时,ExampleTextLabel显示来自数据包1的消息。我知道这一点,因为我正在使用Wireshark来观察传入的数据包。

另一方面,如果我使用InputStreamOptions。部分,没有延误。我收到的数据包显示在Wireshark中。然而,这种解决方案的问题是,大多数时候数据包是损坏的(不完整的)。

谁能给我解释一下这里的问题,有没有什么解决办法?

谢谢!

c# Http服务器使用StreamSocketListener,选项"InputStreamOptions.

回答我的问题

InputStreamOptions。Partial是指异步读操作在有一个或多个字节可用时完成。

这意味着有时它会在没有完成数据包的情况下结束读取操作。我对上面的代码做了以下更改以使其工作(不是实际的代码,只是给出想法的注释):

while (allDataRead)
{
    await input.ReadAsync(buffer, BufferSize, InputStreamOptions.None);
    request.Append(Encoding.UTF8.GetString(data, 0, (Int32)buffer.Length));
    dataRead = buffer.Length;
    //make sure the data read contains the html header, otherwise loop again
    //until you can extract the HTML header.
    //Get the content length from the HTTP header.
    //If the buffer size does not match the content length + html header length,
    //then loop again to get the remaining packets until the buffer length
    //matches the content length + html header length
    //If the content length matches the buffer length then you have received the packet completely.
    //allDataRead=true to exit the loop.
}