Порт StreamSocketListener случайно зависает на Windows IoT UWP приложении - PullRequest
0 голосов
/ 13 апреля 2020

У меня есть написанное мной фоновое приложение UWP, которое работает на Raspberry Pi с последней версией Windows IoT. Его цель - обрабатывать http-запросы и возвращать ответы нескольким мобильным приложениям.

Он отлично работает, за исключением того, что порт прослушивания на сокете иногда зависает. Остальная часть фонового приложения остается отзывчивой, поэтому я знаю, что приложение все еще работает. Но запросы 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);
            }
        }
    }
}

Я подтвердил, что «Компилировать с. NET Native Toolchain "включен в моей конфигурации сборки. И я запускаю это в режиме выпуска.

Я не уверен, что мне нужно сделать что-то другое, чтобы освободить входящие соединения? Возможно, он зависает, потому что поступает несколько запросов одновременно, и он не может его обработать?

Вот пример того, как выглядит netstat, когда порт (в данном случае это 8081) зависает:

  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              *:*                    

На данный момент я открыт для предложений, если кто-то еще столкнулся с подобной ситуацией ....

Спасибо!

1 Ответ

0 голосов
/ 14 апреля 2020

Вы можете попытаться добавить StreamSocket.Dispose Метод для отмены любых ожидающих операций и освобождения всех неуправляемых ресурсов, связанных с объектом StreamSocket.

            listener.Control.KeepAlive = true;

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


                args.Socket.Dispose();
            };
...