/// <summary> /// Echo the message back to the peer /// </summary> /// <param name="peer">The remote peer object</param> /// <param name="eventArguments">The received message event arguments</param> async void EchoMessage(RemotePeer peer, DatagramSocketMessageReceivedEventArgs eventArguments) { if (!peer.IsMatching(eventArguments.RemoteAddress, eventArguments.RemotePort)) { // In the sample we are communicating with just one peer. To communicate with multiple peers // application should cache output streams (i.e. by using a hash map), because creating an output // stream for each received datagram is costly. Keep in mind though, that every cache requires logic // to remove old or unused elements; otherwise cache turns into a memory leaking structure. NotifyUserFromAsyncThread( String.Format( "Got datagram from {0}:{1}, but already 'connected' to {2}", eventArguments.RemoteAddress, eventArguments.RemotePort, peer), NotifyType.ErrorMessage); } try { await peer.OutputStream.WriteAsync(eventArguments.GetDataReader().DetachBuffer()); } 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("Send failed with error: " + exception.Message, NotifyType.ErrorMessage); } }
/// <summary> /// Message received handler /// </summary> /// <param name="socket">The socket object</param> /// <param name="eventArguments">The datagram event information</param> async void MessageReceived(DatagramSocket socket, DatagramSocketMessageReceivedEventArgs eventArguments) { object outObj; if (CoreApplication.Properties.TryGetValue("remotePeer", out outObj)) { EchoMessage((RemotePeer)outObj, eventArguments); return; } // We do not have an output stream yet so create one. try { IOutputStream outputStream = await socket.GetOutputStreamAsync( eventArguments.RemoteAddress, eventArguments.RemotePort); // It might happen that the OnMessage was invoked more than once before the GetOutputStreamAsync // completed. In this case we will end up with multiple streams - make sure we have just one of it. RemotePeer peer; lock (this) { if (CoreApplication.Properties.TryGetValue("remotePeer", out outObj)) { peer = (RemotePeer)outObj; } else { peer = new RemotePeer(outputStream, eventArguments.RemoteAddress, eventArguments.RemotePort); CoreApplication.Properties.Add("remotePeer", peer); } } EchoMessage(peer, eventArguments); } 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("Connect failed with error: " + exception.Message, NotifyType.ErrorMessage); } }
/// <summary> /// Echo the message back to the peer /// </summary> /// <param name="peer">The remote peer object</param> /// <param name="eventArguments">The received message event arguments</param> async void EchoMessage(RemotePeer peer, DatagramSocketMessageReceivedEventArgs eventArguments) { if (!peer.IsMatching(eventArguments.RemoteAddress, eventArguments.RemotePort)) { // In the sample we are communicating with just one peer. To communicate with multiple peers, an // application should cache output streams (e.g., by using a hash map), because creating an output // stream for each received datagram is costly. Keep in mind though, that every cache requires logic // to remove old or unused elements; otherwise, the cache will turn into a memory leaking structure. NotifyUserFromAsyncThread( String.Format( "Got datagram from {0}:{1}, but already 'connected' to {2}", eventArguments.RemoteAddress, eventArguments.RemotePort, peer), NotifyType.ErrorMessage); } try { await peer.OutputStream.WriteAsync(eventArguments.GetDataReader().DetachBuffer()); } 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("Send failed with error: " + exception.Message, NotifyType.ErrorMessage); } }
/// <summary> /// Message received handler /// </summary> /// <param name="socket">The socket object</param> /// <param name="eventArguments">The datagram event information</param> async void MessageReceived(DatagramSocket socket, DatagramSocketMessageReceivedEventArgs eventArguments) { object outObj; if (CoreApplication.Properties.TryGetValue("remotePeer", out outObj)) { EchoMessage((RemotePeer)outObj, eventArguments); return; } // We do not have an output stream yet so create one. try { IOutputStream outputStream = await socket.GetOutputStreamAsync( eventArguments.RemoteAddress, eventArguments.RemotePort); // It might happen that the OnMessage was invoked more than once before the GetOutputStreamAsync call // completed. In this case we will end up with multiple streams - just keep one of them. RemotePeer peer; lock (this) { if (CoreApplication.Properties.TryGetValue("remotePeer", out outObj)) { peer = (RemotePeer)outObj; } else { peer = new RemotePeer(outputStream, eventArguments.RemoteAddress, eventArguments.RemotePort); CoreApplication.Properties.Add("remotePeer", peer); } } EchoMessage(peer, eventArguments); } 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("Connect failed with error: " + exception.Message, NotifyType.ErrorMessage); } }