/// <summary> /// WindowsStoreApp Implementation /// </summary> /// <param name="uri"></param> /// <returns></returns> /// /// // private StreamWebSocket _streamWebSocket; // // private StreamWebSocket _streamWebSocketServer; public object CreateWebSocketClientObject() { StreamWebSocket webSocket = new StreamWebSocket(); //_streamWebSocket = webSocket; //webSocket.Closed += Closed; return webSocket; }
private async void InitializeSocket() { try { StreamWebSocket webSocket = streamWebSocket; if (webSocket == null) { Uri server; if(!Uri.TryCreate("ws://192.168.0.2", UriKind.Absolute, out server)) // działa tylko u mnie albo jak bedziesz podłączony do serwera { return; } webSocket = new StreamWebSocket(); webSocket.Closed += Closed; await webSocket.ConnectAsync(server); streamWebSocket = webSocket; readBuffer = new byte[6000000]; Task recieving = Task.Factory.StartNew(ReceiveData, webSocket.InputStream.AsStreamForRead(), TaskCreationOptions.LongRunning); Task sending = Task.Factory.StartNew(SendData, webSocket.OutputStream, TaskCreationOptions.LongRunning); } } catch(Exception ex) { WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult); } }
public void Reset() { lock (this) { if (readPacket != null) { try { readPacket.DetachStream(); readPacket = null; } catch (Exception exp) { Diag.DebugPrint("Could not detach DataReader: " + exp.Message); } } if (writePacket != null) { try { writePacket.DetachStream(); writePacket = null; } catch (Exception exp) { Diag.DebugPrint("Could not detach DataWriter: " + exp.Message); } } if (socket != null) { socket.Dispose(); socket = null; } if (channel != null) { if (((IDictionary<string, object>)CoreApplication.Properties).ContainsKey(channel.ControlChannelTriggerId)) { CoreApplication.Properties.Remove(channel.ControlChannelTriggerId); } // Call the Dispose() method on the controlchanneltrigger object to release any // OS maintained resources for this channel object. channel.Dispose(); channel = null; } Diag.DebugPrint("CommModule has been reset."); } }
public async Task ConnectAsync(Address address) { StreamWebSocket sws = new StreamWebSocket(); sws.Control.SupportedProtocols.Add(WebSocketSubProtocol); sws.Closed += this.OnWebSocketClosed; Uri uri = new UriBuilder() { Scheme = address.Scheme, Port = GetDefaultPort(address.Scheme, address.Port), Host = address.Host, Path = address.Path }.Uri; await sws.ConnectAsync(uri); this.webSocket = sws; }
private void Stop_Click(object sender, RoutedEventArgs e) { try { if (streamWebSocket != null) { rootPage.NotifyUser("Stopping", NotifyType.StatusMessage); streamWebSocket.Close(1000, "Closed due to user request."); streamWebSocket = null; } else { rootPage.NotifyUser("There is no active socket to stop.", NotifyType.StatusMessage); } } catch (Exception ex) { WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult); if (status == WebErrorStatus.Unknown) { throw; } // Normally we'd use the status to test for specific conditions we want to handle specially, // and only use ex.Message for display purposes. In this sample, we'll just output the // status for debugging here, but still use ex.Message below. rootPage.NotifyUser("Error: " + status, NotifyType.ErrorMessage); OutputField.Text += ex.Message + "\r\n"; } }
public AppContext(CommModule commInstance, StreamWebSocket webSocket, ControlChannelTrigger channel, string id) { WebSocketHandle = webSocket; Channel = channel; ChannelId = id; CommInstance = commInstance; messageQueue = new ConcurrentQueue<string>(); }
public bool SetupTransport(string serviceUri) { bool result = false; lock (this) { // Save these to help reconnect later. serverUri = serviceUri; // Set up the ControlChannelTrigger with the stream socket. result = RegisterWithControlChannelTrigger(serverUri); if (result == false) { Diag.DebugPrint("Failed to sign on and connect"); if (socket != null) { socket.Dispose(); socket = null; readPacket = null; } if (channel != null) { channel.Dispose(); channel = null; } } } return result; }
async Task<bool> RegisterWithCCTHelper(string serverUri) { bool result = false; socket = new StreamWebSocket(); // Specify the keepalive interval expected by the server for this app // in order of minutes. const int serverKeepAliveInterval = 30; // Specify the channelId string to differentiate this // channel instance from any other channel instance. // When background task fires, the channel object is provided // as context and the channel id can be used to adapt the behavior // of the app as required. const string channelId = "channelOne"; // IMPORTANT: Note that this is a websocket sample, therefore the // keepalive task class is provided by Windows for websockets. // For websockets, the system does the keepalive on behalf of the // app but the app still needs to specify this well known keepalive task. // This should be done here in the background registration as well // as in the package manifest. const string WebSocketKeepAliveTask = "Windows.Networking.Sockets.WebSocketKeepAlive"; // Try creating the controlchanneltrigger if this has not been already // created and stored in the property bag. Diag.DebugPrint("RegisterWithCCTHelper Starting..."); ControlChannelTriggerStatus status; Diag.DebugPrint("Create ControlChannelTrigger ..."); // Create the ControlChannelTrigger object and request a hardware slot for this app. // If the app is not on LockScreen, then the ControlChannelTrigger constructor will // fail right away. try { channel = new ControlChannelTrigger(channelId, serverKeepAliveInterval, ControlChannelTriggerResourceType.RequestHardwareSlot); } catch (UnauthorizedAccessException exp) { Diag.DebugPrint("Please add the app to the lock screen." + exp.Message); return result; } Uri serverUriInstance; try { serverUriInstance = new Uri(serverUri); } catch (Exception exp) { Diag.DebugPrint("Error creating URI: " + exp.Message); return result; } // Register the apps background task with the trigger for keepalive. var keepAliveBuilder = new BackgroundTaskBuilder(); keepAliveBuilder.Name = "KeepaliveTaskForChannelOne"; keepAliveBuilder.TaskEntryPoint = WebSocketKeepAliveTask; keepAliveBuilder.SetTrigger(channel.KeepAliveTrigger); keepAliveBuilder.Register(); // Register the apps background task with the trigger for push notification task. var pushNotifyBuilder = new BackgroundTaskBuilder(); pushNotifyBuilder.Name = "PushNotificationTaskForChannelOne"; pushNotifyBuilder.TaskEntryPoint = "BackgroundTaskHelper.PushNotifyTask"; pushNotifyBuilder.SetTrigger(channel.PushNotificationTrigger); pushNotifyBuilder.Register(); // Tie the transport method to the ControlChannelTrigger object to push enable it. // Note that if the transport's TCP connection is broken at a later point of time, // the ControlChannelTrigger object can be reused to plug in a new transport by // calling UsingTransport API again. Diag.DebugPrint("Calling UsingTransport() ..."); try { channel.UsingTransport(socket); // Connect the socket // // If connect fails or times out it will throw exception. await socket.ConnectAsync(serverUriInstance); Diag.DebugPrint("Connected"); // Call WaitForPushEnabled API to make sure the TCP connection has // been established, which will mean that the OS will have allocated // any hardware slot for this TCP connection. // // In this sample, the ControlChannelTrigger object was created by // explicitly requesting a hardware slot. // // On Non-AOAC systems, if app requests hardware slot as above, // the system will fallback to a software slot automatically. // // On AOAC systems, if no hardware slot is available, then app // can request a software slot [by re-creating the ControlChannelTrigger object]. status = channel.WaitForPushEnabled(); Diag.DebugPrint("WaitForPushEnabled() completed with status: " + status); if (status != ControlChannelTriggerStatus.HardwareSlotAllocated && status != ControlChannelTriggerStatus.SoftwareSlotAllocated) { throw new Exception(string.Format("Neither hardware nor software slot could be allocated. ChannelStatus is {0}", status.ToString())); } // Store the objects created in the property bag for later use. // NOTE: make sure these objects are free threaded. STA/Both objects can // cause deadlocks when foreground threads are suspended. CoreApplication.Properties.Remove(channel.ControlChannelTriggerId); var appContext = new AppContext(this, socket, channel, channel.ControlChannelTriggerId); ((IDictionary<string, object>)CoreApplication.Properties).Add(channel.ControlChannelTriggerId, appContext); result = true; Diag.DebugPrint("RegisterWithCCTHelper Completed."); // Almost done. Post a read since we are using streamwebsocket // to allow push notifications to be received. PostSocketRead(MAX_BUFFER_LENGTH); } catch (Exception exp) { Diag.DebugPrint("RegisterWithCCTHelper Task failed with: " + exp.Message); // Exceptions may be thrown for example if the application has not // registered the background task class id for using real time communications // broker in the package appx manifest. } return result; }
private async Task StartAsync() { // Validating the URI is required since it was received from an untrusted source (user input). // The URI is validated by calling TryGetUri() that will return 'false' for strings that are not // valid WebSocket URIs. // Note that when enabling the text box users may provide URIs to machines on the intrAnet // or intErnet. In these cases the app requires the "Home or Work Networking" or // "Internet (Client)" capability respectively. Uri server = rootPage.TryGetUri(ServerAddressField.Text); if (server == null) { return; } streamWebSocket = new StreamWebSocket(); streamWebSocket.Closed += OnClosed; // If we are connecting to wss:// endpoint, by default, the OS performs validation of // the server certificate based on well-known trusted CAs. We can perform additional custom // validation if needed. if (SecureWebSocketCheckBox.IsChecked == true) { // WARNING: Only test applications should ignore SSL errors. // In real applications, ignoring server certificate errors can lead to Man-In-The-Middle // attacks. (Although the connection is secure, the server is not authenticated.) // Note that not all certificate validation errors can be ignored. // In this case, we are ignoring these errors since the certificate assigned to the localhost // URI is self-signed and has subject name = fabrikam.com streamWebSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted); streamWebSocket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName); // Add event handler to listen to the ServerCustomValidationRequested event. This enables performing // custom validation of the server certificate. The event handler must implement the desired // custom certificate validation logic. streamWebSocket.ServerCustomValidationRequested += OnServerCustomValidationRequested; // Certificate validation is meaningful only for secure connections. if (server.Scheme != "wss") { AppendOutputLine("Note: Certificate validation is performed only for the wss: scheme."); } } AppendOutputLine($"Connecting to {server}..."); try { await streamWebSocket.ConnectAsync(server); } catch (Exception ex) // For debugging { streamWebSocket.Dispose(); streamWebSocket = null; AppendOutputLine(MainPage.BuildWebSocketError(ex)); AppendOutputLine(ex.Message); return; } rootPage.NotifyUser("Connected", NotifyType.StatusMessage); // Start a task to continuously read for incoming data Task receiving = ReceiveDataAsync(streamWebSocket); // Start a task to continuously write outgoing data Task sending = SendDataAsync(streamWebSocket); }
private void CloseSocket() { if (streamWebSocket != null) { try { streamWebSocket.Close(1000, "Closed due to user request."); } catch (Exception ex) { AppendOutputLine(MainPage.BuildWebSocketError(ex)); AppendOutputLine(ex.Message); } streamWebSocket = null; } }
// Continuously read incoming data. For reading data we'll show how to use activeSocket.InputStream.AsStream() // to get a .NET stream. Alternatively you could call readBuffer.AsBuffer() to use IBuffer with // activeSocket.InputStream.ReadAsync. private async Task ReceiveDataAsync(StreamWebSocket activeSocket) { Stream readStream = streamWebSocket.InputStream.AsStreamForRead(); int bytesReceived = 0; try { AppendOutputLine("Background read starting."); byte[] readBuffer = new byte[1000]; while (true) { if (streamWebSocket != activeSocket) { // Our socket is no longer active. Stop reading. AppendOutputLine("Background read stopped."); return; } int read = await readStream.ReadAsync(readBuffer, 0, readBuffer.Length); // Do something with the data. // This sample merely reports that the data was received. bytesReceived += read; DataReceivedField.Text = bytesReceived.ToString(); } } catch (Exception ex) { WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult); switch (status) { case WebErrorStatus.OperationCanceled: AppendOutputLine("Background read canceled."); break; default: AppendOutputLine("Error: " + status); AppendOutputLine(ex.Message); break; } } }
// Continuously write outgoing data. For writing data we'll show how to use data.AsBuffer() to get an // IBuffer for use with activeSocket.OutputStream.WriteAsync. Alternatively you can call // activeSocket.OutputStream.AsStreamForWrite() to use .NET streams. private async Task SendDataAsync(StreamWebSocket activeSocket) { int bytesSent = 0; byte[] data = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; AppendOutputLine($"Background sending data in {data.Length} byte chunks each second."); try { // Send until the socket gets closed/stopped while (true) { if (streamWebSocket != activeSocket) { // Our socket is no longer active. Stop sending. AppendOutputLine("Background write stopped."); return; } await activeSocket.OutputStream.WriteAsync(data.AsBuffer()); bytesSent += data.Length; DataSentField.Text = bytesSent.ToString(); // Delay so the user can watch what's going on. await Task.Delay(TimeSpan.FromSeconds(1)); } } catch (Exception ex) { WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult); switch (status) { case WebErrorStatus.OperationCanceled: AppendOutputLine("Background write canceled."); break; default: AppendOutputLine("Error: " + status); AppendOutputLine(ex.Message); break; } } }
private async void OnServerCustomValidationRequested(StreamWebSocket sender, WebSocketServerCustomValidationRequestedEventArgs args) { // In order to call async APIs in this handler, you must first take a deferral and then // release it once you are done with the operation. The "using" statement // ensures that the deferral completes when control leaves the block. bool isValid; using (Deferral deferral = args.GetDeferral()) { // Get the server certificate and certificate chain from the args parameter. isValid = await MainPage.AreCertificateAndCertChainValidAsync(args.ServerCertificate, args.ServerIntermediateCertificates); if (!isValid) { args.Reject(); } } // Continue on the UI thread so we can update UI. var task = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { if (isValid) { AppendOutputLine("Custom validation of server certificate passed."); } else { AppendOutputLine("Custom validation of server certificate failed."); } }); }
// This may be triggered remotely by the server or locally by Close/Dispose() private void Closed(IWebSocket sender, WebSocketClosedEventArgs args) { MarshalText(OutputField, "Closed; Code: " + args.Code + ", Reason: " + args.Reason + "\r\n"); if (streamWebSocket != null) { streamWebSocket.Dispose(); streamWebSocket = null; } }
public StreamWebSocketEvents(StreamWebSocket This) { this.This = This; }
private async void Start_Click(object sender, RoutedEventArgs e) { // Have we connected yet? if (streamWebSocket != null) { rootPage.NotifyUser("Already connected", NotifyType.StatusMessage); return; } // Validating the URI is required since it was received from an untrusted source (user input). // The URI is validated by calling TryGetUri() that will return 'false' for strings that are not // valid WebSocket URIs. // Note that when enabling the text box users may provide URIs to machines on the intrAnet // or intErnet. In these cases the app requires the "Home or Work Networking" or // "Internet (Client)" capability respectively. Uri server; if (!rootPage.TryGetUri(ServerAddressField.Text, out server)) { return; } try { rootPage.NotifyUser("Connecting to: " + server, NotifyType.StatusMessage); streamWebSocket = new StreamWebSocket(); // Dispatch close event on UI thread. This allows us to avoid synchronizing access to streamWebSocket. streamWebSocket.Closed += async (senderSocket, args) => { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Closed(senderSocket, args)); }; await streamWebSocket.ConnectAsync(server); readBuffer = new byte[1000]; // Start a background task to continuously read for incoming data Task receiving = Task.Factory.StartNew(Scenario2ReceiveData, streamWebSocket.InputStream.AsStreamForRead(), TaskCreationOptions.LongRunning); // Start a background task to continuously write outgoing data Task sending = Task.Factory.StartNew(Scenario2SendData, streamWebSocket.OutputStream, TaskCreationOptions.LongRunning); rootPage.NotifyUser("Connected", NotifyType.StatusMessage); } catch (Exception ex) // For debugging { if (streamWebSocket != null) { streamWebSocket.Dispose(); streamWebSocket = null; } WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult); switch (status) { case WebErrorStatus.CannotConnect: case WebErrorStatus.NotFound: case WebErrorStatus.RequestTimeout: rootPage.NotifyUser("Cannot connect to the server. Please make sure " + "to run the server setup script before running the sample.", NotifyType.ErrorMessage); break; case WebErrorStatus.Unknown: throw; default: rootPage.NotifyUser("Error: " + status, NotifyType.ErrorMessage); break; } OutputField.Text += ex.Message + "\r\n"; } }
public WebSocketTransport(StreamWebSocket webSocket) { this.webSocket = webSocket; }