Сетевое соединение с приложениями UWP

У меня есть два приложения Windows UWP. Один из них (сервер) работает на Raspberry Pi 2 в Windows IoT (10586.0). Другой (клиент) работает на любом устройстве с Windows 10 в той же сети.

Я хочу, чтобы приложения разговаривали друг с другом. На данный момент я просто хочу отправить простую строку от клиента на сервер. Позже сериализованные данные должны передаваться по сети.

Это код для серверного приложения:

namespace LCARSHomeAutomation
{
/// <summary>
/// Eine leere Seite, die eigenständig verwendet oder zu der innerhalb eines Rahmens navigiert werden kann.
/// </summary>
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        try {
            EstablishNetworking();
            txb_Events.Text += "Server Running";
        }catch (Exception ex)
        {
            txb_Events.Text += ex.Message;
        }

        
    }

    private async void EstablishNetworking()
    {
        await StartListener();
    }

    public async Task StartListener()
    {
        StreamSocketListener listener = new StreamSocketListener();
        listener.ConnectionReceived += OnConnection;

        listener.Control.KeepAlive = true;

        try
        {
            await listener.BindServiceNameAsync("5463");
            
        }
        catch (Exception ex)
        {
            if (SocketError.GetStatus(ex.HResult) == SocketErrorStatus.Unknown)
            {
                throw;
            }
            //Logs.Add(ex.Message);
            txb_Events.Text += ex.Message;
        }

    }

    private async void OnConnection(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
    {
        Stream inStream = args.Socket.InputStream.AsStreamForRead();
        StreamReader reader = new StreamReader(inStream);
        string request = await reader.ReadLineAsync();

        await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                                   () =>
                                   {
                                        // Your UI update code goes here!
                                        txb_Events.Text += (String)request;
                                   });


    }

    private async Task ConnectSocket()
    {
        StreamSocket socket = new StreamSocket();

        socket.Control.KeepAlive = false;

        HostName host = new HostName("localhost");

        try
        {
            await socket.ConnectAsync(host, "5463");

            Stream streamOut = socket.OutputStream.AsStreamForWrite();
            StreamWriter writer = new StreamWriter(streamOut);
            string request = "Test Self App \n";
            await writer.WriteLineAsync(request);
            await writer.FlushAsync();

            socket.Dispose();
        }
        catch (Exception ex)
        {
            txb_Events.Text += ex.Message;
            //Logs.Add(ex.Message)
        }


    }

    private async void btn_Send_Click(object sender, RoutedEventArgs e)
    {
        await ConnectSocket();
    }
    
}
}

Как видите, я устанавливаю сетевое соединение с тем же приложением на том же хосте и отправляю строку Test Self App. Некоторое время это работает нормально, но через некоторое время я получаю сообщение об ошибке:

Возникло исключение: 'System.Runtime.InteropServices.COMException' в mscorlib.ni.dll

Информация WinRT: невозможно установить соединение, потому что целевая машина активно отказалась от него.

Итак, это мой первый вопрос: что это за ошибка и как ее исправить?

Другое дело: я не могу установить сетевое соединение между сервером и клиентом. Не знаю, что делаю не так. Это код Клиента:

namespace LCARSRemote
{
/// <summary>
/// Eine leere Seite, die eigenständig verwendet oder zu der innerhalb eines Rahmens navigiert werden kann.
/// </summary>
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
    }

    private async void btn_Send_Click(object sender, RoutedEventArgs e)
    {
        StreamSocket socket = new StreamSocket();

        HostName host = new HostName("localhost"); //Replace with coorect hostname when running on RPi

        try
        {
            try {
                await socket.ConnectAsync(host, "5463");
            }
            catch(Exception ex)
            {
                txb_Events.Text += ex.Message;
            }

            Stream streamOut = socket.OutputStream.AsStreamForWrite();
            StreamWriter writer = new StreamWriter(streamOut);
            string request = "Remote App Test";
            await writer.WriteLineAsync(request);
            await writer.FlushAsync();

            socket.Dispose();

        }
        catch (Exception ex)
        {
            txb_Events.Text += ex.Message;
            //Logs.Add(ex.Message)
        }

    }
}
}

Когда я нажимаю на btn_Send, я получаю сообщение об ошибке

Попытка подключения не удалась, потому что подключенная сторона не ответила должным образом по прошествии определенного периода времени, или установление соединения не удалось из-за того, что подключенный хост не ответил.

а также

Метод был вызван в неожиданное время. (Исключение из HRESULT: 0x8000000E)

Что я делаю неправильно? Возможно, мне стоит сказать, что я относительно новичок в программировании сетевых подключений, сокетов и т. Д.

Спасибо за любую помощь!


person drummercrm    schedule 07.04.2016    source источник
comment
Вы изменили имя хоста на что-нибудь толковое? Вы проверили правила своего брандмауэра?   -  person Rowland Shaw    schedule 07.04.2016
comment
Я также пробовал с отключенным брандмауэром. Я пробовал 127.0.0.1 в качестве имени хоста, я также пробовал minwinpc (имя RPi в локальной сети), но ничего не работало.   -  person drummercrm    schedule 08.04.2016
comment
Вы пробовали использовать IP-адрес своего Pi?   -  person Rowland Shaw    schedule 11.04.2016
comment
Вы этого не сказали, в вашем коде указано localhost (что, очевидно, не будет работать, поскольку клиент и сервер находятся на разных хостах); вы говорите, что пробовали IP-адрес localhost (127.0.0.1) и имя хоста, но не фактический IP-адрес. Вы действительно пробовали свой код, когда оба работают на одном хосте?   -  person Rowland Shaw    schedule 11.04.2016
comment
Я пробовал оба: сервер, работающий на RPi, с клиентом, работающим на ПК, а также сервер и клиент, работающие на ПК. В зависимости от сценария я изменил HostName в клиентском коде. Я пробовал использовать имя хоста RPi, а также IP-адрес RPi. Когда я пытаюсь отправить сообщение с сервера самому себе (см. Код Task ConnectSocket), я иногда могу щелкнуть, а затем получаю сообщение о том, что машина активно отказалась от соединения.   -  person drummercrm    schedule 11.04.2016


Ответы (3)


Вам следует попробовать использовать StreamSocket API в UWP. Этот образец репо содержит как серверный, так и клиентский код: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/StreamSocket.

Метод был вызван в неожиданное время. (Исключение из HRESULT: 0x8000000E)

Эта ошибка произошла у меня, когда я дважды пытаюсь вызвать ConnectAsync, я думаю, вы можете проверить свою логику или отладить, чтобы подтвердить в вашем случае.

person thang2410199    schedule 07.04.2016
comment
Я взглянул на эти примеры, но они мне не помогли. Ошибки все еще существуют. Я также пытался использовать DataWriter / DataWriter вместо StreamReader / -Writer (как в примере выше), но это тоже не сработало. - person drummercrm; 08.04.2016

Первая ошибка

Возникло исключение: 'System.Runtime.InteropServices.COMException' в mscorlib.ni.dll

Информация WinRT: невозможно установить соединение, потому что целевая машина активно отказалась от него.

Это связано с тем, что сокет все еще открыт с предыдущим запросом и еще не закрыт. Так что поймайте эту ошибку и попробуйте снова подключиться.

Попытка подключения не удалась, потому что подключенная сторона не ответила должным образом по прошествии определенного периода времени, или установление соединения не удалось из-за того, что подключенный хост не ответил.

Это связано с тем, что сервер и клиент находятся на одном компьютере, я сталкиваюсь с той же проблемой, предположительно, вы можете запустить из командной строки с повышенными привилегиями.

checknetisolation loopbackexempt -d -n= {package family} 

чтобы решить эту проблему.

Это решение не сработало для меня. Таким образом, ваш сервер должен работать на Pi, а клиент должен работать на вашем настольном ПК, чтобы Windows 10 UWP могла подключиться к нему. Насколько я могу судить, Windows 10 не поддерживает петлевое соединение для приложений UWP.

Если вы действительно хотите запустить сервер сокетов / веб-сервер node.js, универсальные приложения Windows могут быть хорошим подходом.

https://ms-iot.github.io/content/en-US/win10/samples/NodejsWU.htm

or

RestUP  https://github.com/tomkuijsten/restup
person Stuart Smith    schedule 30.04.2016

В зависимости от того, сколько данных вы говорите и каков конечный вариант использования, Amazon AWS IoT Platform может быть тем, на что стоит обратить внимание. Это круто по ряду причин. В частности, мне нравится, что целевое устройство может быть отключено во время передачи.

Это бесплатно (250 000 сообщений) в течение первого года и 5 долларов за миллион сообщений после этого. Каждый 512-байтовый блок считается кредитом на 1 сообщение.

person ObjectType    schedule 08.04.2016
comment
Для меня это невозможно, потому что я хочу, чтобы приложения разговаривали друг с другом даже при отсутствии подключения к Интернету. - person drummercrm; 08.04.2016