UWP не может создать локальное соединение между двумя приложениями - PullRequest
1 голос
/ 15 июня 2019

Я пытаюсь настроить TCP-соединение между двумя приложениями UWP. Он отлично работает, когда сервер и клиент работают в одном приложении. Но когда я перемещаю серверную часть в одно приложение, а клиентскую часть - в другое, ConnectAsync выдает исключение (сервер не отвечает вовремя).

Оба приложения имеют возможность настройки частных сетей. И, как я понимаю из страниц MSDN, мне не нужно беспокоиться о добавлении исключения в CheckNetIsolation, пока я запускаю приложения в отладчике. (Я установил флажок на страницах свойств de debug проекта, на обоих включен «Разрешить петлю локальной сети».

Брандмауэр тоже полностью отключен.

В netstat я вижу, что порт открыт и находится в состоянии прослушивания:

 TCP    0.0.0.0:1337           PC-BAS:0               LISTENING

Код, который я использую, скопирован из примера MSDN и не изменяется, за исключением части, в которой клиент и сервер размещены в двух отдельных приложениях.

Клиент:

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        //this.StartServer();
        this.StartClient();
    }

    private async void StartClient()
    {
        try
        {
            // Create the StreamSocket and establish a connection to the echo server.
            using (var streamSocket = new Windows.Networking.Sockets.StreamSocket())
            {
                // The server hostname that we will be establishing a connection to. In this example, the server and client are in the same process.
                var hostName = new Windows.Networking.HostName("127.0.0.1");

                this.clientListBox.Items.Add("client is trying to connect...");

                await streamSocket.ConnectAsync(hostName, StreamSocketAndListenerPage.PortNumber);

                this.clientListBox.Items.Add("client connected");

                // Send a request to the echo server.
                string request = "Hello, World!";
                using (Stream outputStream = streamSocket.OutputStream.AsStreamForWrite())
                {
                    using (var streamWriter = new StreamWriter(outputStream))
                    {
                        await streamWriter.WriteLineAsync(request);
                        await streamWriter.FlushAsync();
                    }
                }

                this.clientListBox.Items.Add(string.Format("client sent the request: \"{0}\"", request));

                // Read data from the echo server.
                string response;
                using (Stream inputStream = streamSocket.InputStream.AsStreamForRead())
                {
                    using (StreamReader streamReader = new StreamReader(inputStream))
                    {
                        response = await streamReader.ReadLineAsync();
                    }
                }

                this.clientListBox.Items.Add(string.Format("client received the response: \"{0}\" ", response));
            }

            this.clientListBox.Items.Add("client closed its socket");
        }
        catch (Exception ex)
        {
            Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
            this.clientListBox.Items.Add(webErrorStatus.ToString() != "Unknown" ? webErrorStatus.ToString() : ex.Message);
        }
    }

Сервер:

    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        try
        {
            var streamSocketListener = new Windows.Networking.Sockets.StreamSocketListener();

            // The ConnectionReceived event is raised when connections are received.
            streamSocketListener.ConnectionReceived += this.StreamSocketListener_ConnectionReceived;

            // Start listening for incoming TCP connections on the specified port. You can specify any port that's not currently in use.
            await streamSocketListener.BindServiceNameAsync("1337");

        }
        catch (Exception ex)
        {
            Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
        }
    }

    private async void StreamSocketListener_ConnectionReceived(Windows.Networking.Sockets.StreamSocketListener sender, Windows.Networking.Sockets.StreamSocketListenerConnectionReceivedEventArgs args)
    {
        string request;
        using (var streamReader = new StreamReader(args.Socket.InputStream.AsStreamForRead()))
        {
            request = await streamReader.ReadLineAsync();
        }

        // Echo the request back as the response.
        using (Stream outputStream = args.Socket.OutputStream.AsStreamForWrite())
        {
            using (var streamWriter = new StreamWriter(outputStream))
            {
                await streamWriter.WriteLineAsync(request);
                await streamWriter.FlushAsync();
            }
        }

        sender.Dispose();
    }

Что я делаю не так?

Обновление

Я пытался исключить оба приложения с помощью checknetisolation:

C: \ Users \ baspr> checknetisolation LoopbackExempt -s

Список зацикленных исключений AppContainers

1 ---------------------------------------- ------------------------- Имя: bb9c7c66-7c8e-4736-b328-1b107e10a7a9_wkb2562a8jp2j SID: S-1-15-2-762432806-102046223-720402593-3591906639-2980959523-756744333-221970472

[2] -------------------------------------------- --------------------- Имя: client_wkb2562a8jp2j SID: S-1-15-2-2445159625-2135182799-200836335-1591194441-3000767028-3156876117-3345333685

клиент:

C:\Users\baspr>checknetisolation LoopbackExempt -a -n=client_wkb2562a8jp2j
OK.

Сервер:

C:\Users\baspr>checknetisolation LoopbackExempt -a -n=bb9c7c66-7c8e-4736-b328-1b107e10a7a9_wkb2562a8jp2j
OK.

Хотя мне интересно, если это вообще необходимо, как указано в MSDN:

Loopback и отладчик

По умолчанию запуск в отладчике Visual Studio включает исходящие loopback автоматически только для этого сеанса отладки. Вы не должны должны сделать что-нибудь, пока флажок зацикливания установлен в настройки отладчика для вашего запуска проекта. Если вы хотите реализовать слушатель сокета, вы должны включить локальную петлю для входящего соединения (см. ниже).

В любом случае это ничего не меняет. Я все еще не могу подключиться к серверу. Я попробовал оба своих локальных IP-адреса в качестве петлевого адреса (192.168.1.2 и 127.0.0.1). Не работает

Надеюсь, что кто-нибудь может пролить свет на это ...

...