c# - Grupo de multidifusión UDP en Windows Phone 8
sockets windows-phone-8 (3)
¿Alguna vez has intentado unirte a otro grupo de multidifusión? Porque 224.0.1.1 parece estar en uso a partir de las asignaciones de IANA. Usted encuentra todo el here .
Tal vez en Windows Phone 8, algunos servicios están más obligados a escuchar los mensajes entrantes (por ejemplo, un servicio de red que se ejecuta en modo kernel) y nunca se reenvían a usted.
OK, este es uno que he estado tratando de descifrar por unos días. Tenemos una aplicación en Windows Phone 7 donde los teléfonos se unen a un grupo de multidifusión y luego envían y reciben mensajes al grupo para hablar entre ellos. Nota: esta es una comunicación de teléfono a teléfono.
Ahora intento portar esta aplicación a Windows Phone 8, usando la función ''Convertir a teléfono 8'' en Visual Studio 2012, hasta ahora, todo bien. Hasta que intente probar la comunicación de teléfono a teléfono. Los teléfonos parecen unirse bien al grupo, y envían los datagramas OK. Incluso reciben los mensajes que envían al grupo; sin embargo, ningún teléfono recibe un mensaje de otro teléfono.
Aquí está el código de muestra detrás de mi página:
// 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");
}
Para probar simplemente la pila UDP, descargué el ejemplo de MSDN que se encuentra here y lo probé en un par de dispositivos con Windows Phone 7 y funciona como se esperaba. Luego me convertí a Windows Phone 8 y se implementó en mis teléfonos, nuevamente los dispositivos parecen iniciar su conexión, y el usuario puede ingresar su nombre. Sin embargo, nuevamente los dispositivos no pueden ver ni comunicarse con otros dispositivos.
Finalmente implementé una prueba de comunicación simple usando la nueva implementación de DatagramSocket, y de nuevo veo una iniciación exitosa, pero no hay comunicación entre dispositivos.
Este es el mismo código detrás de la página que utiliza la implementación del socket de datagramas:
// 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;
}
}
Anoche llevé los auriculares a casa para probarlos en la red inalámbrica de mi casa, y cuando recibo una comunicación exitosa con el dispositivo.
Para recapitular, mi código heredado de Windows Phone 7 funciona bien en mi red de trabajo. El puerto para Windows Phone 8 (sin cambio de código real) no envía comunicaciones entre dispositivos. Este código funciona en mi red doméstica. El código se ejecuta con el depurador adjunto y no hay signos de errores o excepciones en ningún lugar durante la ejecución.
Los teléfonos que uso son:
Windows Phone 7 - Nokia Lumia 900 (* 2), Nokia Lumia 800 (* 3) Windows Phone 8 - Nokia Lumia 920 (* 1), Nokia Limia 820 (* 2)
Todos ejecutan el último sistema operativo y están en modo desarrollador. El entorno de desarrollo es Windows 8 Enterprise que ejecuta Visual Studio 2012 Professional
No puedo decirle mucho sobre la red inalámbrica de trabajo, aparte de los dispositivos del teléfono 7 no tienen problemas.
En cuanto a la red inalámbrica doméstica que utilicé, es solo un enrutador BT Broadband básico sin alterar ninguno de los ajustes ''out-box''.
Claramente hay un problema con la forma en que las dos redes están configuradas, pero también hay un problema muy claro con la forma en que Windows Phone 8 implementa los mensajes UDP.
Cualquier comentario sería apreciado ya que esto me está volviendo loco en este momento.
La multidifusión UDP funciona de forma bastante extraña en el teléfono 7 de Windows según mi experiencia, por lo que debe realizar el mismo trámite para Windows Phone 8.
Aquí está mi experiencia:
- verifique qué es oficialmente compatible, por ejemplo, con Windows Phone OS 7.1 (el último sistema operativo que probé antes de cambiar), se admiten TCP unicast, unicast UDP y clientes de multidifusión UDP.
- Algunas versiones de Windows Phone permiten recibir una sesión UDP solo si el cliente la abre por primera vez y la sesión se recibe en no más de 10 segundos, esto parece una especie de seguridad en Windows Phone.
- intente con diferentes direcciones: las direcciones de multidifusión en el rango de 224.0.0.0 a 224.0.0.255 inclusive son direcciones de multidifusión reservadas "bien conocidas".
- Verifique tanto en la máquina virtual como en un dispositivo telefónico real, el comportamiento puede diferir.
Noté que usas el loopback. Creo que significa que cuando envíe un mensaje de su cliente, recibirá también el mensaje que envió. Esto significa que su controlador de recepción se activará. Tiene el efecto de borrar el búfer de recepción de una manera aparentemente no amenazada. Intenta poner algo de prueba en tu método de recepción y observa si algo está sucediendo, pero en su lugar podrías no usar el búfer de recepción compartido en cualquier caso.