2012-11-23 25 views
55

OK questo è uno che ho cercato di capire per alcuni giorni. Abbiamo un'applicazione su Windows Phone 7 in cui i telefoni si uniscono a un gruppo multicast e quindi inviano e ricevono messaggi al gruppo per parlare tra loro. Nota: questa è una comunicazione telefonica.Gruppo multicast UDP su Windows Phone 8

Ora sto cercando di effettuare il porting di questa applicazione su Windows Phone 8 - utilizzando la funzionalità "Converti in telefono 8" in Visual Studio 2012 - finora così buona. Fino a quando non provo a testare la comunicazione tra telefono e telefono. I telefoni sembrano unirsi al gruppo e mandano i datagrammi OK. Ricevono persino i messaggi che inviano al gruppo - tuttavia, nessun telefono riceve mai un messaggio da un altro portatile.

Ecco il codice di esempio dietro alla mia pagina:

// 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"); 
} 

Al fine di testare semplicemente fuori lo stack UDP, ho scaricato il campione da MSDN trovato here e ho provato questo su un paio di Windows Phone 7 dispositivi e funziona come previsto. Poi mi sono convertito a Windows Phone 8 e distribuito ai miei telefoni, di nuovo i dispositivi sembrano iniziare la loro connessione, e l'utente può inserire il loro nome. Tuttavia, ancora una volta i dispositivi non possono vedere o comunicare con altri dispositivi.

Infine ho implementato un semplice test di comunicazione utilizzando la nuova implementazione di DatagramSocket e di nuovo vedo un'iniziazione positiva, ma nessuna comunicazione tra dispositivi.

Questo è lo stesso codice dietro la pagina utilizzando l'attuazione presa datagram:

// 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; 
    } 
} 

Ieri sera ho preso la casa di telefonini per metterli alla prova sulla mia rete wireless domestica, bassa ed ecco ricevo comunicazione del dispositivo di successo.

Quindi per ricapitolare: il mio codice Windows Phone legacy funziona correttamente sulla mia rete di lavoro. La porta a Windows Phone 8 (nessuna modifica effettiva del codice) non invia comunicazioni tra dispositivi. Questo codice funziona sulla mia rete domestica. Il codice viene eseguito con il debugger allegato e non vi sono segni di errori o eccezioni ovunque durante l'esecuzione.

I portatili che sto usando sono:

Windows Phone 7 - Nokia Lumia 900 (* 2), Nokia Lumia 800 (* 3) Windows Phone 8 - Nokia Lumia 920 (* 1), Nokia Limia 820 (* 2)

Questi sono tutti in esecuzione sul sistema operativo più recente e sono in modalità sviluppatore. L'ambiente di sviluppo è Windows 8 Enterprise che esegue Visual Studio 2012 Professional

Non posso dirti molto sulla rete wireless di lavoro, a parte i dispositivi Phone 7 non hanno problemi.

Per quanto riguarda la rete wireless domestica che ho usato, questo è solo un router BT Broadband di base con nessuna delle impostazioni "out the box" alterate.

Ovviamente c'è un problema con il modo in cui sono configurate le due reti, ma c'è anche molto chiaramente un problema con il modo in cui Windows Phone 8 implementa i messaggi UDP.

Qualsiasi input sarebbe apprezzato poiché questo mi sta facendo impazzire in questo momento.

+1

L'ultimo commento che ho ricevuto da Microsoft è che questo potrebbe riguardare un errore nello stack. A partire da ora sto aspettando di sentire di nuovo da loro. Aggiornerò questo post come e quando ne sentirò di più. Tuttavia, l'implementazione di WinRT può essere fatta funzionare, se la prima riga dell'implementazione SendSocketRequest viene modificata in questo modo: 'var stream = attende socket.GetOutputStreamAsync (new Windows.Networking.HostName (IPAddress.Broadcast.ToString()), GROUP_PORT .ToString()); ' –

+0

Prova a utilizzare indirizzi di gruppo diversi come" 239.0.0.11 ". – nucleons

+0

Ancora una parola da Microsoft? Sto colpendo lo stesso problema e non ho trovato un work-around. – briandunnington

risposta

1

Ho notato che usi il loopback. Penso che significhi che quando invii un messaggio dal tuo cliente, riceverai anche il messaggio che hai inviato. Ciò significa che il tuo gestore di ricezione verrà attivato.Ha l'effetto di svuotare il buffer di ricezione in modo apparentemente poco sicuro. Prova a mettere un po 'di try catch nel tuo metodo di ricezione e vedere se sta accadendo qualcosa di spiacevole, ma potresti semplicemente non usare il buffer di ricezione condiviso in ogni caso.

1

Hai mai provato a entrare in un altro gruppo multicast? Perché 224.0.1.1 sembra essere in uso a partire dagli incarichi IANA. Puoi trovare tutto il here.

Forse su Windows Phone 8 alcuni servizi sono più limitati per ascoltare i messaggi in arrivo (ad esempio un servizio di rete che è in esecuzione in modalità kernel) e non vengono mai inoltrati.

1

UDP multicast funziona abbastanza stranamente sotto windows phone 7 dalla mia esperienza così si dovrebbe checkout la stessa per Windows Phone 8.

Ecco la mia esperienza:

  1. controllo ciò che è ufficialmente supportato, per esempio in Windows Phone OS 7.1 (ultimo sistema operativo che ho provato prima di passare), sono supportati i client TCP unicast, UDP unicast e UDP multicast.
  2. alcune versioni del telefono Windows consentono di ricevere una sessione UDP solo se il client la apre per la prima volta e la sessione viene ricevuta entro non più di 10 secondi, questo sembra una sorta di cosa di sicurezza su Windows Phone.
  3. provare con indirizzi diversi: gli indirizzi multicast nell'intervallo da 224.0.0.0 a 224.0.0.255 inclusi sono indirizzi multicast riservati "ben noti".
  4. Controllare sia nella macchina virtuale che in un dispositivo telefonico reale, il comportamento potrebbe essere diverso.
Problemi correlati