Windows Phone 8上的UDP多播组
好吧,这是我一直想弄明白的一个日子。 我们在Windows Phone 7上有一个应用程序,在这个应用程序中,电话join一个多播组,然后向该组发送和接收消息以相互交谈。 请注意 – 这是电话通话。
现在我试图将这个应用程序移植到Windows Phone 8上 – 使用Visual Studio 2012中的“转换为电话8”function – 到目前为止这么好。 直到我尝试testing手机通讯。 手机似乎join了组,他们发送数据包OK。 他们甚至收到他们发给群组的消息 – 但是,任何手机都不会收到来自另一个手机的消息。
以下是我的页面后面的示例代码:
// Constructor public MainPage() { InitializeComponent(); } // The address of the multicast group to join. // Must be in the range from 224.0.0.0 to 239.255.255.255 private const string GROUP_ADDRESS = "224.0.1.1"; // The port over which to communicate to the multicast group private const int GROUP_PORT = 55562; // A client receiver for multicast traffic from any source UdpAnySourceMulticastClient _client = null; // Buffer for incoming data private byte[] _receiveBuffer; // Maximum size of a message in this communication private const int MAX_MESSAGE_SIZE = 512; private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) { _client = new UdpAnySourceMulticastClient(IPAddress.Parse(GROUP_ADDRESS), GROUP_PORT); _receiveBuffer = new byte[MAX_MESSAGE_SIZE]; _client.BeginJoinGroup( result => { _client.EndJoinGroup(result); _client.MulticastLoopback = true; Receive(); }, null); } private void SendRequest(string s) { if (string.IsNullOrWhiteSpace(s)) return; byte[] requestData = Encoding.UTF8.GetBytes(s); _client.BeginSendToGroup(requestData, 0, requestData.Length, result => { _client.EndSendToGroup(result); Receive(); }, null); } private void Receive() { Array.Clear(_receiveBuffer, 0, _receiveBuffer.Length); _client.BeginReceiveFromGroup(_receiveBuffer, 0, _receiveBuffer.Length, result => { IPEndPoint source; _client.EndReceiveFromGroup(result, out source); string dataReceived = Encoding.UTF8.GetString(_receiveBuffer, 0, _receiveBuffer.Length); string message = String.Format("[{0}]: {1}", source.Address.ToString(), dataReceived); Log(message, false); Receive(); }, null); } private void Log(string message, bool isOutgoing) { if (string.IsNullOrWhiteSpace(message.Trim('\0'))) { return; } // Always make sure to do this on the UI thread. Deployment.Current.Dispatcher.BeginInvoke( () => { string direction = (isOutgoing) ? ">> " : "<< "; string timestamp = DateTime.Now.ToString("HH:mm:ss"); message = timestamp + direction + message; lbLog.Items.Add(message); // Make sure that the item we added is visible to the user. lbLog.ScrollIntoView(message); }); } private void btnSend_Click(object sender, RoutedEventArgs e) { // Don't send empty messages. if (!String.IsNullOrWhiteSpace(txtInput.Text)) { //Send(txtInput.Text); SendRequest(txtInput.Text); } } private void btnStart_Click(object sender, RoutedEventArgs e) { SendRequest("start now"); }
为了简单地testingUDP堆栈,我从MSDN下载了样本,并在Windows Phone 7设备上进行了testing,结果如预期。 然后,我转换到Windows Phone 8,并部署到我的手机,设备似乎再次启动连接,用户可以input他们的名字。 但是,设备再次无法看到或与其他设备通信。
最后,我使用新的DatagramSocket实现实现了一个简单的通信testing,我再次看到成功的启动,但没有设备间的通信。
这是使用数据报套接字实现的页面背后的相同代码:
// Constructor public MainPage() { InitializeComponent(); } // The address of the multicast group to join. // Must be in the range from 224.0.0.0 to 239.255.255.255 private const string GROUP_ADDRESS = "224.0.1.1"; // The port over which to communicate to the multicast group private const int GROUP_PORT = 55562; private DatagramSocket socket = null; private void Log(string message, bool isOutgoing) { if (string.IsNullOrWhiteSpace(message.Trim('\0'))) return; // Always make sure to do this on the UI thread. Deployment.Current.Dispatcher.BeginInvoke( () => { string direction = (isOutgoing) ? ">> " : "<< "; string timestamp = DateTime.Now.ToString("HH:mm:ss"); message = timestamp + direction + message; lbLog.Items.Add(message); // Make sure that the item we added is visible to the user. lbLog.ScrollIntoView(message); }); } private void btnSend_Click(object sender, RoutedEventArgs e) { // Don't send empty messages. if (!String.IsNullOrWhiteSpace(txtInput.Text)) { //Send(txtInput.Text); SendSocketRequest(txtInput.Text); } } private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) { socket = new DatagramSocket(); socket.MessageReceived += socket_MessageReceived; try { // Connect to the server (in our case the listener we created in previous step). await socket.BindServiceNameAsync(GROUP_PORT.ToString()); socket.JoinMulticastGroup(new Windows.Networking.HostName(GROUP_ADDRESS)); System.Diagnostics.Debug.WriteLine(socket.ToString()); } catch (Exception exception) { throw; } } private async void SendSocketRequest(string message) { // Create a DataWriter if we did not create one yet. Otherwise use one that is already cached. //DataWriter writer; var stream = await socket.GetOutputStreamAsync(new Windows.Networking.HostName(GROUP_ADDRESS), GROUP_PORT.ToString()); //writer = new DataWriter(socket.OutputStream); DataWriter writer = new DataWriter(stream); // 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. // stream.WriteAsync( writer.WriteString(message); // Write the locally buffered data to the network. try { await writer.StoreAsync(); Log(message, true); System.Diagnostics.Debug.WriteLine(socket.ToString()); } catch (Exception exception) { throw; } finally { writer.Dispose(); } } void socket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args) { try { uint stringLength = args.GetDataReader().UnconsumedBufferLength; string msg = args.GetDataReader().ReadString(stringLength); Log(msg, false); } catch (Exception exception) { throw; } }
昨天晚上,我把手机带回家,在我的家庭无线networking上testing,看到我的设备通信成功。
所以回顾一下 – 我的传统Windows Phone 7代码在我的工作networking上运行良好。 到Windows Phone 8的端口(没有实际的代码更改)不会发送设备间通信。 此代码在我的家庭networking上工作。 代码在附加debugging器的情况下运行,在执行过程中没有任何错误或exception的迹象。
我使用的手机是:
Windows Phone 7 – 诺基亚Lumia 900(* 2),诺基亚Lumia 800(* 3)Windows Phone 8 – 诺基亚Lumia 920(* 1),诺基亚Limia 820(* 2)
这些都运行最新的操作系统,并处于开发模式。 开发环境是运行Visual Studio 2012 Professional的Windows 8 Enterprise
我不能告诉你有关无线networking的工作 – 除了Phone 7设备没有问题。
至于我使用的家庭无线networking,这只是一个基本的BT宽带路由器,没有任何“箱子”设置改变。
显然这两个networking的configuration方式存在问题,但Windows Phone 8实现UDP消息的方式也很明显。
任何意见,将不胜感激,因为这是现在让我疯了。
我注意到你使用了回送。 我认为这意味着当你从你的客户端发送消息时,你也会收到你发送的消息。 这意味着你的接收处理程序将触发。 它具有清除接收缓冲区看似unthreadsafe的方式的效果。 尝试在接收方法中join一些try catch,看看是否有什么不幸的事情发生,但是在任何情况下你都可能不使用共享接收缓冲区。
你有没有尝试join另一个组播组? 因为224.0.1.1似乎在IANA任务中正在使用。 你在这里find所有的东西 。
也许在Windows Phone 8上,某些服务比较紧密,以侦听进入的消息(例如,以内核模式运行的networking服务),并且它们永远不会转发给您。
从我的经验来看,在Windows Phone 7下,UDP组播的工作原理非常奇怪,所以你应该为Windows Phone 8签出相同的协议。
这是我的经验:
- 检查什么是正式支持,例如在Windows Phone OS 7.1(我切换前的最后一个操作系统),TCP单播,UDP单播和UDP多播客户端支持。
- 某些版本的Windows手机只有在客户端首次打开它并在不超过10秒内收到会话的情况下才允许接收UDP会话,这似乎是Windows Phone上的某种安全措施。
- 尝试使用不同的地址:范围从224.0.0.0到224.0.0.255的组播地址是“已知”的保留组播地址。
- 检查虚拟机和真实电话设备中的行为可能会有所不同。