StreamSocketListener 端口随机挂在 Windows IoT UWP 应用程序上

StreamSocketListener port randomly hangs on Windows IoT UWP application

我有一个我编写的 UWP 后台应用程序,它 运行s 在 Raspberry Pi 运行ning 最新版本的 Windows IoT 上。它的目的是处理 http 请求和 return 对多个移动应用程序的响应。

效果很好,只是套接字上的侦听端口似乎偶尔会挂起。后台应用程序的其余部分保持响应,所以我知道该应用程序仍在 运行ning。但是 http 请求停止响应。通常只需登录 IoT 仪表板并重新启动我的应用程序即可解决问题。但是我不明白为什么应用程序偶尔会挂起。

这是我认为相关的代码段:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using Windows.ApplicationModel.Background;
using Windows.Networking.Sockets;

namespace MyApp.Sandbox
{
    public class SystemTest : IBackgroundTask
    {
        private StreamSocketListener listener = null;

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            StartServer();
        }

        public async void StartServer()
        {
            try
            {
                int port = 8189;

                listener = new StreamSocketListener();
                var currentSetting = listener.Control.QualityOfService;
                listener.Control.QualityOfService = SocketQualityOfService.LowLatency;

                await listener.BindServiceNameAsync(port.ToString());

                listener.ConnectionReceived += async (sender, args) =>
                {
                    var request = new StringBuilder();
                    using (var input = args.Socket.InputStream.AsStreamForRead())
                    {
                        int maxBuffer = 8192;
                        int index = 0;

                        List<byte> line = new List<byte>();
                        int b;
                        while (true)
                        {
                            try
                            {
                                b = input.ReadByte();
                                line.Add((byte)b);

                                if (b == 10 && line.Count >= 2)
                                {
                                    if (line[line.Count - 2] == 13 && line[line.Count - 1] == 10)
                                    {
                                        byte[] byteArray = line.ToArray();
                                        var dataString = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
                                        request.Append(dataString);
                                        line = new List<byte>();

                                        if (request.ToString().StartsWith("GET"))
                                        {
                                            break;
                                        }

                                        if (request.ToString().StartsWith("POST") &&
                                            request.ToString().Contains(Environment.NewLine + Environment.NewLine))
                                        {
                                            string contentLength = GetValueFromHeader("Content-Length", request.ToString());
                                            if (!contentLength.Equals(""))
                                            {
                                                int length = Convert.ToInt32(contentLength);
                                                if (length > 0)
                                                {
                                                    byteArray = new byte[length];
                                                    input.Read(byteArray, 0, length);
                                                    dataString = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
                                                    request.Append(dataString);
                                                }
                                            }
                                            break;
                                        }
                                    }
                                }

                                index++;

                                if (index > maxBuffer)
                                {
                                    break;
                                }
                            }
                            catch
                            {
                                break;
                            }
                        }
                        input.Dispose();
                    }

                    using (var output = args.Socket.OutputStream)
                    {
                        using (var response = output.AsStreamForWrite())
                        {
                            var requestLines = request.ToString().Split(' ');
                            var url = requestLines.Length > 1 ? requestLines[1] : string.Empty;

                            string postLine = null;
                            if (requestLines.Length > 0)
                            {
                                if (requestLines[0] == "POST")
                                {
                                    postLine = requestLines[requestLines.Length - 1];
                                }
                            }

                            string str = null;
                            try
                            {
                                // handle response here which fills "str"
                            }
                            catch (Exception innerEx)
                            {
                                Debug.WriteLine(innerEx.Message);
                                Debug.WriteLine(innerEx.StackTrace);
                            }

                            var html = Encoding.UTF8.GetBytes(str);
                            using (var bodyStream = new MemoryStream(html))
                            {
                                var header = $"HTTP/1.1 200 OK\r\nContent-Length: {bodyStream.Length}\r\nContent-Type: application/json\r\ncharset: UTF-8\r\nConnection: close\r\n\r\n";
                                var headerArray = Encoding.UTF8.GetBytes(header);
                                await response.WriteAsync(headerArray, 0, headerArray.Length);
                                await bodyStream.CopyToAsync(response);
                                await response.FlushAsync();
                            }
                        }
                        output.Dispose();
                    }
                };
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                Debug.WriteLine(ex.StackTrace);
            }
        }
    }
}

我已确认在我的构建配置中启用了 "Compile with .NET Native Toolchain"。我正在 运行 在发布模式下使用它。

我不确定是否需要做一些不同的事情来释放传入连接?是不是因为同时有多个请求,无法处理而挂了?

这是端口(在本例中为 8081)挂起时 netstat 的示例:

  TCP    192.168.1.190:8081     5.101.0.209:32880      CLOSE_WAIT
  TCP    192.168.1.190:8081     5.101.0.209:33494      CLOSE_WAIT
  TCP    192.168.1.190:8081     5.101.0.209:60412      CLOSE_WAIT
  TCP    192.168.1.190:8081     Mike-PC:59879          CLOSE_WAIT
  TCP    192.168.1.190:8081     Mike-PC:59880          CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:43096    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:43110    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:43114    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:43120    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:43130    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:43742    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:43744    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:43750    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:43822    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:43914    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:43986    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:48646    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:48648    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:48702    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:48724    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:48774    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:48776    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:48820    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:48834    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:48918    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:49036    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:49058    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:49284    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:49416    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:49672    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:49680    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:50360    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:50566    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:50718    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:50724    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:50734    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:50938    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:51082    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:51524    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:51880    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:51946    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:52146    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:52212    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:52224    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:52310    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:53126    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:53206    CLOSE_WAIT
  TCP    192.168.1.190:8081     Galaxy-S20-5G:53284    CLOSE_WAIT
  TCP    192.168.1.190:8081     192.227.118.82:1550    ESTABLISHED
  TCP    192.168.1.190:59613    52.242.211.89:https    ESTABLISHED
  TCP    [::]:22                myapp:0                LISTENING
  TCP    [::]:135               myapp:0                LISTENING
  TCP    [::]:445               myapp:0                LISTENING
  TCP    [::]:5985              myapp:0                LISTENING
  TCP    [::]:8080              myapp:0                LISTENING
  TCP    [::]:8081              myapp:0                LISTENING
  TCP    [::]:47001             myapp:0                LISTENING
  TCP    [::]:49664             myapp:0                LISTENING
  TCP    [::]:49665             myapp:0                LISTENING
  TCP    [::]:49667             myapp:0                LISTENING
  UDP    0.0.0.0:123            *:*                    
  UDP    0.0.0.0:5050           *:*                    
  UDP    0.0.0.0:5353           *:*                    
  UDP    0.0.0.0:5355           *:*                    
  UDP    0.0.0.0:29819          *:*                    
  UDP    0.0.0.0:51049          *:*                    
  UDP    [::]:123               *:*                    
  UDP    [::]:5353              *:*                    
  UDP    [::]:5355              *:*                    

在这一点上,如果其他人 运行 遇到类似情况,我愿意接受建议....

谢谢!

您可以尝试添加 StreamSocket.Dispose 方法来中止任何挂起的操作并释放与 StreamSocket 对象关联的所有非托管资源。

            listener.Control.KeepAlive = true;

            listener.ConnectionReceived += async (sender, args) =>
            {
                //Your codes


                args.Socket.Dispose();
            };