Search code examples
c#uwpstream-socket-client

How can I receive data from server by streamsocket continuously?


I am a WPF programmer and now is a beginner of UWP.

I need to write a new program to connect a remote machine now. And the machine will send data to the client at times.

I wanna that whenever the machine sends the data, the client will get it at once.

In WPF I can use the Asynchronous Client Socket, whenever there is a data to the client, the ReceiveCallback will get it at once as shown in this example.

However, in UWP it seems has not the Asynchronous Client Socket. I used the SteamSocket to connect the remote machine successfully as below:

 Task.Run(async()=>{
                try
                {
                    StreamSocket SS = new StreamSocket();
                    await SS.ConnectAsync(new Windows.Networking.HostName("192.168.200.111"), "23");

                    DataWriter writer = new DataWriter(SS.OutputStream);
                    string content = "ST";
                    byte[] data = Encoding.UTF8.GetBytes(content);
                    writer.WriteBytes(data); 
                    await writer.StoreAsync();
                    writer.DetachStream();
                    writer.Dispose();

                    DataReader reader = new DataReader(SS.InputStream);
                    reader.InputStreamOptions = InputStreamOptions.Partial;
                    await reader.LoadAsync(1024);
                    string response = reader.ReadString(reader.UnconsumedBufferLength);
                    Debug.WriteLine(response);                       
                }
                catch(Exception ex)
                {
                    throw ex;
                }
            });

Whereas, these codes can only read the data when you use the DataReader, but not with an event to show it when received the data at once.

By using a loopback may solve it and I don't want the code being so ugly with the loopback.

I googled but found nothing useful about this.

I asked Microsoft engineer about this and he told me to use the SocketActivityTrigger, I don't want to use it for it not only hard to use but also is a background worker. Even I exit the UWP program it will still connect to the remote machine and receive the data continuously.

Would you please tell me how to solve it?


To @Nico Zhu:

 private void Button_Click(object sender, RoutedEventArgs e)
        {
            Task.Run(async()=>{
                try
                {                    
                    StreamSocketListener SSL = new StreamSocketListener();
                    SSL.ConnectionReceived += SSL_ConnectionReceived;
                    await SSL.BindEndpointAsync(new Windows.Networking.HostName("192.168.200.111"), "23");

                }
                catch(Exception ex)
                {
                    throw ex;
                }
            });
        }

        private void SSL_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
        {
            Debug.WriteLine("123");
        }

I used the StreamSocketListener, but after I ran the program, it reports '

{System.Runtime.InteropServices.COMException (0x80072741): The requested address is not valid in its context

   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at App2.MainPage.<<Button_Click>b__2_0>d.MoveNext()}

' What's wrong with this?


Solution

  • Thanks for @Nico Zhu helping me so much. Finally, I found a strange way to do it: using the socket of WPF in UWP

    But it is strange that the socket of WPF has not the Asynchronous Client Socket in UWP, so that I can only do it like this:

     await Task.Factory.StartNew(async () =>
                {
                    IPEndPoint ip = new IPEndPoint(IPAddress.Parse("192.168.200.111"), 23);
                    Socket S = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    S.Connect(ip);
                    S.Send(Encoding.UTF8.GetBytes("SS" + Environment.NewLine));
                    while (true)
                    {
                        byte[] buffer = new byte[1024];
                        if (S.Available != 0)
                        {
                            S.Receive(buffer);
                            Debug.WriteLine(Encoding.UTF8.GetString(buffer));
                            Debug.WriteLine("");
                            await Task.Delay(100);
                        }
                    }
                });