Статьи

Вы — Контроллер: шаг в WP7 -> Сеть Win8

Я не мог устоять, я должен был работать над своим Windows 8 Port of Flipped (который, кажется, идет гладко) и заканчивать некоторые другие проекты, но гламур одолел меня, когда я выкатился с обложки и вот мы здесь.

Одна из моих давних мечт о разработке игр (даже до XNA) состояла в том, чтобы иметь возможность взять мое мобильное устройство и использовать его в качестве альтернативного дисплея или дополнительного контроллера, в то время, когда это был мой надежный Windows Mobile PPC, времена менялись но мое видение все еще свежо.

Некоторое время я думал об этом между Windows Phone и настольным ПК, и когда мы делали Vequencer, мы экспериментировали с этим.

Теперь Windows 8 входит в мир, и все перчатки сняты, здесь у нас есть две дополняющие платформы (тем более Windows Phone 8?), Новый этап для развития моей мечты.

PS Это моя первая попытка ведения блога с Word в качестве основы Live, и что более важно, Windows Live Writer на моем образе Win 7, и я ловко пытаюсь написать это из Windows 8


Источник для поста можно найти здесь на codeplex —  http://bit.ly/NxxVLb  (нужен лучший дом для моих новых образцов блога)

*НОТА

Прежде, чем я забуду, и если у вас возникнут проблемы с кодом ПОМНИТЕ, сетевое соединение UDP не поддерживается в эмуляторе WP7 или Metro Simulator. Оба должны работать на устройстве или, в случае Win 8, на ПК, чтобы сеть работала. Урок, усвоенный во время тестирования Vequencer: D


Цель

Просто для этой небольшой демонстрации я расскажу о том, как заставить эти две платформы общаться друг с другом, но, поскольку используется UDP Multi-Cast, он также может быть любым клиентом!

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


Клиент WP7 с помощью библиотеки «UdpAnySourceMulticastChannel»

Когда мы делали Vequencer, мы просматривали все сетевые примеры в поисках лучшего способа подключения нескольких устройств Windows Phone (ну, на самом деле это сделал Мэтт Лейси @MrLacey) и в конечном итоге остановились на UDP, который был похоронен в одном из примеров MS. хорошая маленькая библиотека помощников / оболочек, которая называется «UdpAnySourceMulticastChannel».

Короче говоря, это просто обернуло всю необходимую работу для создания «UdpAnySourceMulticastClient» и функций для отправки и получения сообщений — все это было красиво упаковано в один класс (ну почти). Я не собираюсь публиковать это здесь, как вы можете найти в образце.

Его использование о так просто с этим на месте.

Сначала настройте его и подключите необходимые события:

private void CreateChannel()
{
 this.Channel = new UdpAnySourceMulticastChannel(GroupAddress, GroupPort);
 
this.RegisterEvents();
 
this.Channel.Open();
}

Тогда отправка сообщения становится такой же простой, как:

Channel.Send("Message from remote {0}", "client");

Получение сообщений просто означает обработку события PacketReceived таким образом:

void Channel_PacketReceived(object sender, UdpPacketReceivedEventArgs e)
{
 NotifyUser(string.Format("Message Received : {0}", e.Message));
}
 
//Prompt the user on screen
private void NotifyUser(string message)
{
 TextBlock textbox = new TextBlock();
 textbox.Text = message;
 textbox.Foreground = new SolidColorBrush(Colors.White);
 Messages.Children.Add(textbox);
}

Здесь я просто обновляю пользовательский интерфейс любым текстом, который я получаю от других машин, проверяю оставшуюся часть источника для получения более подробной информации или более детального изучения того, как «UdpAnySourceMulticastChannel» обрабатывает сетевой трафик.

Так что это клиент WP7, который является очень простым, теперь для основного события.


Windows 8 Сеть и документация разглагольствования

Теперь одна из вещей, которые меня поразили, это доступная документация и примеры, к сожалению, это также одна из моих самых больших проблем. Да, там гораздо больше контента и больше образцов, чем вы можете потрясти достаточно большой клюшкой для большинства общих задач, которые вам нужно выполнить в Windows 8, так что для 80% людей вы будете проходить без проблем.

См. Образец сети «DatagramSocket» здесь — http://bit.ly/MIJbzH (создайте сокет слушателя и запустите его / создайте сокет сервера и отправляйте сообщения, используя DataWriter и DataReader для обработки потоковых данных) — см. образец для получения дополнительной информации

ОДНАКО, где он падает, просто между трещинами, хотя есть полная документация для этого сетевого сценария, для окружающих сценариев, которые имеют функции, НЕТ, один из них — многоадресная сеть UDP, которая важна для локального играть в сценарии, как я делаю здесь, но с помощью и некоторыми подсказками ( http://bit.ly/MIJxXl ) я наконец-то туда попал.

Увы, в документации также не упоминаются возможности, на которые ваше приложение должно подписаться, чтобы работать (они по умолчанию отключены), поэтому, если при программировании Windows 8 появляется сообщение об ошибке «Отказано в доступе», нет, вы ничего не сделали неправильно, вы просто забыл сказать Windows, что вам нужно сделать это. Просто дважды щелкните «Package.appxmanifest» и включите те возможности, которые вам нужны (отстой и смотри!), Те, кто пришел из Windows Phone, привыкнут к этому (вроде), новичкам в Metro лучше читать!

[/ Напыщенная]


Сеть UDP — простой способ

Итак, чтобы перейти к короткой версии, вот пошаговое руководство для сетей UDP под Windows 8, во-первых, как и в случае большинства сетей, работающих по принципу «огонь и забудь», нам нужен сокет, с которым мы собираемся поговорить, и DataWriter для упаковки данных для отправки:

DatagramSocket socket;
DataWriter writer;

Далее нам просто нужно инициализировать их и подготовить их к использованию:

socket = new DatagramSocket();
socket.MessageReceived += ListenerMessageReceived;
 
// Start listen operation.
try
{
 await socket.BindServiceNameAsync(GroupPort.ToString());
 socket.JoinMulticastGroup(GroupAddress);
 
var stream = await socket.GetOutputStreamAsync(GroupAddress, GroupPort.ToString());
 writer = new DataWriter(stream);
 
}
catch (Exception exception)
{
 
// If this is an unknown status it means that the error is fatal and retry will likely fail.
 if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
 {
 throw;
 }
 
NotifyUserFromAsyncThread("Start listening failed with error: " + exception.Message, NotifyType.ErrorMessage);
}

Теперь несколько моментов в приведенном выше коде:

  • Обязательно связать событие «MessageReceived» после инициализации DatagramSocket, если вы этого не сделаете, он просто потерпит крах. Вам не нужно ничего обрабатывать, это может быть пустой метод, но вы должны связать его.
  • Функция, которую вы используете, чтобы использовать обработчик «async», так как почти все вызовы в Windows 8 являются «ожидаемыми» функциями, о которых вы должны знать уже (слишком велик, чтобы идти сюда)
  • Прежде чем присоединиться к сеансу многоадресной рассылки или даже стандартному подключению, вы должны связать сокет с типом конечной точки, здесь я использую функцию «BindServiceNameAsync» и передаю ей предварительно заданный адрес многоадресной рассылки.
  • Тогда вам просто нужно инициализировать DataWriter, чтобы использовать поток вывода из Socket и все готово

Ну, почти.

Вот где две вещи заставили меня потратить практически весь день и несколько волос на это:

  1. Прежде всего, вам нужны дополнительные «возможности», включенные в вашем приложении, чтобы сделать это, после игры с несколькими я остановился на возможности «Домашняя или рабочая сеть», как показано ниже:

2. Затем была инициализация DataWriter, вы заметите, что из приведенного выше кода я не просто передаю ему поток вывода из сокета напрямую, вы ДОЛЖНЫ сначала его инициализировать, потому что вы используете многоадресную передачу UDP. (Вы не должны делать это с обычными сокетами!) — Это задокументировано, черт возьми, нет (отсюда и напыщенная речь). Таким образом, в действительности вы должны инициализировать поток, проходящий по адресу конечной точки UDP и порту, через который вы хотите передавать (я использую адрес « 224.225.226.227 »
и порт « 54345 »), затем вы можете инициализировать DataWriter, используя этот новый поток.

После этого становится более нормальным, чтобы отправить сообщение, просто сделайте следующее:

// Сначала записать длину строки как значение UINT32, а затем строку. Запись данных в устройство записи просто хранит данные в памяти.

// Write first the length of the string as UINT32 value followed up by the string. Writing data to the writer will just store data in memory.
string stringToSend = "Hello";
writer.WriteString(stringToSend);
 
// Write the locally buffered data to the network.
try
{
 await writer.StoreAsync();
 NotifyUserFromAsyncThread("\"" + stringToSend + "\" sent successfully.", NotifyType.Info);
}

Там, где вы загружаете тест в буфер DataWriter, а затем, когда вы закончите, просто очистите буфер, используя метод «StoreAsync», который перенесет его со скоростью песчанок.

Единственное другое предупреждение, о котором следует знать, это то, что все обратные вызовы от сетевых вызовов должны быть безопасно перенаправлены обратно в пользовательский интерфейс, для этого я реализовал простой метод диспетчера, чтобы обернуть мой вызов, чтобы обновить экран таким образом:

private void NotifyUserFromAsyncThread(string strMessage, NotifyType type)
{
 var ignore = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => NotifyUser(strMessage, type));
}

В исходном коде есть несколько других нюансов, чтобы сделать вещи красивыми, большая часть которых вырвана прямо из образца DataGram Socket, с несколькими настройками, чтобы разместить его на одной странице (мне нравятся примеры экранов для их внешнего вида, но попытка разорвать их до фактического использования — это кошмар, должен быть отдельный отдельный образец, делающий все это, чтобы его было легче потреблять)


Продолжение следует

Я вернусь к этой теме в недалеком будущем. Я намеревался показать хороший полностью работающий графический пример, показывающий, как люди играют в карты, а планшет — в колоду (все по-умному), но, как вы видите, я потратил слишком много времени, чтобы заставить все это работать.

далее