UWP app System.Net.Sockets - localhost

Madhu 96 Reputation points
2020-03-04T12:57:44.277+00:00

Hi,

When reading about sockets in UWP, I have seen that we can't use sockets to communicate between 2 apps in the same device with localhost. (Not sure exactly when it works and not).

I just need to clarify on that. If I connect to some other app running in the same device as my UWP app, should I be able to connect to that other app using System.Net.Sockets? Or it is not allowed?
My UWP app will be the client and there will be another app (most probably .net app) which works as the server. So if I call the server from my app like this it seems to work. But based on some articles I am not sure whether there are any restrictions on this. Will this work in a UWP app submitted to Store or will there be issues?

           clientSocket = new Socket(AddressFamily.InterNetwork,  
           SocketType.Dgram, ProtocolType.Udp);  

            //IP address of the server machine  
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");  
            //Server is listening on port 1000  
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 1000);  

            epServer = (EndPoint)ipEndPoint;  
            clientSocket.BeginSendTo(byteData, 0, byteData.Length, SocketFlags.None, epServer, new AsyncCallback(OnSend), null);  

Update : please see the Note here. https://learn.microsoft.com/en-us/windows/uwp/networking/sockets
It says 'Windows disallows establishing a socket connection (Sockets or WinSock) between two UWP apps running on the same machine'. So this applies only for 2 UWP apps? If one is a UWP app and the other is a .net app then it will not be an issue?

Thanks
Madhu

Universal Windows Platform (UWP)
{count} votes

2 answers

Sort by: Most helpful
  1. Peter Smith 581 Reputation points Microsoft Employee
    2020-03-04T21:46:39.213+00:00

    From a UWP app, you cannot connect to "any" other process on the same system. This is a security restriction, enforced by the firewall.

    It may appear to work when you are using Visual Studio and debugging your program, but that's because the firewall rules are relaxed while debugging.

    Why is "any" in quote marks? Because apparently you ARE allowed to have a socket between two apps in the same package -- but when you do that, note that you may have trouble shipping the resulting app package in the store.

    1 person found this answer helpful.

  2. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-03-04T14:54:02.4+00:00

    Hi,
    there's no problem to use sockets in UWP. Try following demo:

    XAML

    <Page  
        x:Class="UWP10App1VB.Page13"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        xmlns:local="using:UWP10App1VB"  
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
        mc:Ignorable="d"  
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">  
      <Page.Resources>  
        <local:Page13VM x:Key="vm"/>  
      </Page.Resources>  
      <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"  
                  DataContext="{StaticResource vm}">  
        <Button Content="Receive" Command="{Binding Cmd}"/>  
        <TextBlock Text="{Binding Display, Mode=OneWay}"/>  
      </StackPanel>  
    </Page>  
    

    Code

    Imports System.Net  
    Imports System.Net.Sockets  
    Imports System.Threading  
    Imports Newtonsoft.Json  
    Imports Windows.Networking  
    Imports Windows.Networking.Sockets  
      
    ''' <summary>  
    ''' An empty page that can be used on its own or navigated to within a Frame.  
    ''' </summary>  
    Public NotInheritable Class Page13  
      Inherits Page  
      
    End Class  
      
    Public Class Page13VM  
      Implements INotifyPropertyChanged, IDisposable  
      
      Private _server As New Page13Server  
      
      Private nr As Integer = 0  
      Private hostName As String = "127.0.0.1"  
      Private serverPort As String = "5000"  
      Public Property Display As String = "<empty>"  
      Public ReadOnly Property Cmd As ICommand = New RelayCommand(AddressOf CmdExec)  
      Private Async Sub CmdExec(obj As Object)  
        Try  
          Dim socket As New StreamSocket()  
          Dim serverHost As New HostName(hostName)  
          Await socket.ConnectAsync(serverHost, serverPort)  
      
          ' Data object for sending  
          nr += 1  
          Dim d1 As New Page13Data With {.ID = nr, .Info1 = $"Row {nr}", .Info2 = "for response"}  
      
          ' Write data to the server.  
          Using outp As Stream = socket.OutputStream.AsStreamForWrite()  
            Using wrt As New StreamWriter(outp)  
              Await wrt.WriteLineAsync(JsonConvert.SerializeObject(d1))  
              Await wrt.FlushAsync()  
            End Using  
          End Using  
      
          ' Data object für Empfang  
          Dim d2 As Page13Data = Nothing  
      
          ' Read data from erver.  
          Using inp As Stream = socket.InputStream.AsStreamForRead()  
            Using rdr As New StreamReader(inp)  
              Dim resp As String = Await rdr.ReadLineAsync()  
              'Display = resp  
              d2 = JsonConvert.DeserializeObject(Of Page13Data)(resp)  
              Display += $"{Environment.NewLine}Received Object from Server ID:{ d2.ID}, Info1: { d2.Info1}, Info2: { d2.Info2}"  
            End Using  
          End Using  
        Catch ex As Exception  
          Display = ex.ToString()  
        End Try  
        OnPropertyChanged(NameOf(Display))  
      End Sub  
      
      Private Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged  
      Public Sub OnPropertyChanged(Optional propertyName As String = "")  
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))  
      End Sub  
      
    #Region "IDisposable Support"  
      Private disposedValue As Boolean ' To detect redundant calls  
      
      ' IDisposable  
      Protected Overridable Sub Dispose(disposing As Boolean)  
        Me._server?.Cancel()  
        disposedValue = True  
      End Sub  
      
      Protected Overrides Sub Finalize()  
        Dispose(False)  
        MyBase.Finalize()  
      End Sub  
      
      Public Sub Dispose() Implements IDisposable.Dispose  
        Dispose(True)  
        GC.SuppressFinalize(Me)  
      End Sub  
    #End Region  
      
    End Class  
      
    Public Class Page13Data  
      Public Property ID As Integer  
      Public Property Info1 As String  
      Public Property Info2 As String  
    End Class  
      
    Friend Class Page13Server  
      Private _listeningPort As Integer = 5000  
      Private _listenningIPAddress As String = "127.0.0.1"  
      Dim source As New CancellationTokenSource()  
      Dim token As CancellationToken  
      
      Public Sub New()  
        token = source.Token  
        Call (New TaskFactory(token)).StartNew(AddressOf Start)  
      End Sub  
      
      Friend Sub Cancel()  
        source.Cancel()  
      End Sub  
      
      Public Async Sub Start()  
        Dim ipAddre As IPAddress = IPAddress.Parse(_listenningIPAddress)  
        Dim listener As TcpListener = New TcpListener(ipAddre, _listeningPort)  
        Try  
          listener.Start()  
          LogMessage("Server is running")  
          LogMessage("Listening on port {_listeningPort}")  
          While True  
            LogMessage("Waiting for connections...")  
            Dim client = Await listener.AcceptTcpClientAsync()  
            HandleConnectionAsync(client)  
          End While  
        Catch ex As Exception  
          LogMessage(ex.ToString())  
        End Try  
      End Sub  
      
      Private Async Sub HandleConnectionAsync(client As TcpClient)  
        client.LingerState.Enabled = False  
        Dim clientInfo As String = client.Client.RemoteEndPoint.ToString()  
        LogMessage(String.Format("Got connection request from {0}", clientInfo))  
        Try  
          Dim d As Page13Data = Nothing  
          Using str As NetworkStream = client.GetStream()  
            Using wrt As New StreamWriter(str)  
              str.ReadTimeout = 600  
              Using rdr As New StreamReader(str)  
                Dim req As String = Await rdr.ReadLineAsync()  
                LogMessage($"Receive from Client:{req}")  
                d = GetData(Of Page13Data)(req)  
                LogMessage($"Received Object from Client ID:{d.ID}, Info1:{d.Info1}, Info2:{d.Info2}")  
                d.Info2 = $"Received from Server for ID {d.ID}"  
                Dim resp As String = GetJSon(Of Page13Data)(d)  
                Await wrt.WriteLineAsync(resp)  
                Await wrt.FlushAsync()  
              End Using  
            End Using  
          End Using  
        Catch exp As Exception  
          LogMessage(exp.ToString())  
        Finally  
          LogMessage($"Closing the client connection - {clientInfo}")  
          client.Close()  
        End Try  
      End Sub  
      Friend Sub LogMessage(msg As String)  
        Debug.WriteLine($"Server:{ msg}")  
      End Sub  
      
      Private Function GetData(Of T)(json As String) As T  
        Return JsonConvert.DeserializeObject(Of T)(json)  
      End Function  
      Private Function GetJSon(Of T)(obj As T) As String  
        Return JsonConvert.SerializeObject(obj)  
      End Function  
      
    End Class