Wie Kommunkation zwischen Windows und Windows Phone herstellen?

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von sothere.

    Wie Kommunkation zwischen Windows und Windows Phone herstellen?

    Hallöchen ihr lieben,
    ich habe mal wieder angefangen, zu programmieren und wollte ein älteres Projekt aufgreifen und dazu eine App schreiben.
    Ich hatte gehofft, wie TCP zwischen Windows Forms Anwendung und Windows Phone Strings übertragen zu können, am besten via TCP. Allerdings bekomme ich es überhaupt nicht hin, einen TCP-Server zu erstellen, der in beide Richtungen (Empfangen und Schreiben) mit Windows Phone kommunizieren kann. Das beste, was ich hin bekommen habe, war das das Windows Phone Nachrichten an die Windows Forms Anwendung schickt, aber das wars dann auch. Habe das ganze jetzt komplett gelöscht und suche eigentlich erstmal komplett nach Ansätzen.
    Liebe Grüße
    sothere

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „sothere“ ()

    Ich habe inzwischen das hier als Beispiel für den Client gefunden: msdn.microsoft.com/de-de/libra…s/apps/xaml/jj150599.aspx
    Fehlt mir nur noch die Serverseite, allerdings müsste diese eben auch selber senden können. Hab den ganzen Abend jetzt schon rumgegoogelt und nichts gefunden. Vielleicht hat ja doch noch jemand von euch ne Idee, sonst lege ich das zu den Akten
    Liebe Grüße
    sothere
    Hi
    generell brauchst du nur eine TcpListener-Instanz und mehere TcpClients auf der Clientseite.
    AcceptTcpClient wartet auf einen weiteren Client (es gibt auch asynchrone Verfahren, die funktionieren aber eben entsprechend anders, sind natürlich auch in der TcpListener-Klasse zu finden) und gibt diesen zurück. Über den assoziierten Stream kann dann der Datentransfer stattfinden. TcpListener kann (und wird) mehrere TcpClient-Instanzen empfangen, d.h. ich würde auch die Möglichkeit mehrerer Clients verfügbar machen. Verbindungsverluste sollte man auch einplanen.

    Damit eine Verbindung auch außerhalb des lokalen Netzwerkes erfolgen kann, muss eine Portfreigabe erfolgen oder ein verbindungsloses Protokoll (Udp) mit hole punching verwendet werden. Ein Server kommuniziert hierbei Port und IP-Adresse der jeweiligen Clients (einfach ein wenig in hole punching einlesen, falls du's brauchst), d.h. du brauchst ihn zumindest als Mittelsmann. Im lokalen Netzwerk kann man übrigens bspw. broadcasts verwenden, um den Client zu ermitteln, der angefordert wird.

    Es spielt übrigens, zumindest, wenn du Tcp verwendest, keine Rolle, woher und wohin der Stream geht, da es sich um ein standardisiertes Protokoll handelt.

    Viele Grüße
    ~blaze~
    @ErfinderDesRades : Tolles Tutorial!

    Ich habe jetzt mit zwei Tutorials mir was zusammengeschustert, was soweit funktioniert, bin zufrieden :D Danke für die Hilfe!

    Spoiler anzeigen


    Client WP 8.1

    VB.NET-Quellcode

    1. Private Socket As StreamSocket
    2. Private connected As Boolean = False
    3. Private Async Sub button_verbinden_Click(sender As Object, e As RoutedEventArgs) Handles button_verbinden.Click
    4. Try
    5. If connected = False Then
    6. textBox_adresse.IsEnabled = False
    7. textBox_port.IsEnabled = False
    8. button_verbinden.IsEnabled = False
    9. progress_verbinden.IsActive = True
    10. Socket = New StreamSocket
    11. Await Socket.ConnectAsync(New HostName(textBox_adresse.Text), textBox_port.Text)
    12. StartListening()
    13. Dim deviceInfo As New Windows.Security.ExchangeActiveSyncProvisioning.EasClientDeviceInformation()
    14. Dim _name = deviceInfo.FriendlyName
    15. progress_verbinden.IsActive = False
    16. connected = True
    17. pivot_main.SelectedIndex = 1
    18. End If
    19. Catch ex As Exception
    20. connected = False
    21. textBox_adresse.IsEnabled = True
    22. textBox_port.IsEnabled = True
    23. button_verbinden.IsEnabled = True
    24. progress_verbinden.IsActive = False
    25. End Try
    26. End Sub
    27. Private Async Sub StartListening()
    28. Dim reader As New DataReader(Socket.InputStream)
    29. Do
    30. Try
    31. Dim sizeFieldCount As UInteger = Await reader.LoadAsync(CUInt(Runtime.InteropServices.Marshal.SizeOf(New UInteger)))
    32. If sizeFieldCount <> Runtime.InteropServices.Marshal.SizeOf(New UInteger) Then
    33. Return
    34. End If
    35. Dim stringLength As UInteger = reader.ReadUInt32()
    36. Dim actualStringLength As UInteger = Await reader.LoadAsync(stringLength)
    37. If stringLength <> actualStringLength Then
    38. Return
    39. End If
    40. Dim MsgReceived As String = reader.ReadString(actualStringLength)
    41. MsgHandler(MsgReceived)
    42. Debug.WriteLine(MsgReceived)
    43. Catch ex As Exception
    44. connected = False
    45. textBox_adresse.IsEnabled = True
    46. textBox_port.IsEnabled = True
    47. button_verbinden.IsEnabled = True
    48. Socket = New StreamSocket
    49. pivot_main.SelectedIndex = 0
    50. Debug.WriteLine("Connection closed")
    51. Exit Do
    52. End Try
    53. Loop
    54. End Sub
    55. Private Async Sub SendMsg(ByVal msg As String)
    56. Dim stringToSend As String = msg
    57. Dim writer As New DataWriter(Socket.OutputStream)
    58. writer.WriteUInt32(writer.MeasureString(stringToSend))
    59. Debug.WriteLine(writer.MeasureString(stringToSend))
    60. writer.WriteString(stringToSend)
    61. Await writer.StoreAsync()
    62. writer.DetachStream()
    63. writer.Dispose()
    64. End Sub


    Server WinForm

    VB.NET-Quellcode

    1. Public RemotePort As Integer = 8010
    2. #Region "Server"
    3. Private tcpListener As TcpListener
    4. Private listenThread As Thread
    5. Private connectedClients As Integer = 0
    6. Private Sub StartServer()
    7. tcpListener = New TcpListener(IPAddress.Any, RemotePort)
    8. listenThread = New Thread(New ThreadStart(AddressOf ListenForClients))
    9. listenThread.Start()
    10. End Sub
    11. Private Sub StopServer()
    12. Try
    13. tcpListener.Stop()
    14. listenThread.Abort()
    15. Catch ex As Exception
    16. End Try
    17. End Sub
    18. Private Sub ListenForClients()
    19. tcpListener.Start()
    20. While True
    21. Try
    22. Dim client As TcpClient = Me.tcpListener.AcceptTcpClient()
    23. connectedClients += 1
    24. Me.BeginInvoke(Sub()
    25. RemoteMenu.lb_clients.Text = connectedClients.ToString & " Benutzer verbunden"
    26. Debug.WriteLine("Remote User verbunden")
    27. End Sub)
    28. Dim clientThread As New Thread(New ParameterizedThreadStart(AddressOf HandleClientComm))
    29. clientThread.Start(client)
    30. Catch ex As Exception
    31. End Try
    32. End While
    33. End Sub
    34. Dim clients As New List(Of NetworkStream)
    35. Private Sub HandleClientComm(client As Object)
    36. Dim tcpClient As TcpClient = DirectCast(client, TcpClient)
    37. Dim clientStream As NetworkStream = tcpClient.GetStream()
    38. clients.Add(clientStream)
    39. Dim message As Byte() = New Byte(4095) {}
    40. Dim bytesRead As Integer
    41. While True
    42. bytesRead = 0
    43. Try
    44. bytesRead = clientStream.Read(message, 0, 4096)
    45. Catch
    46. Exit Try
    47. End Try
    48. If bytesRead = 0 Then
    49. connectedClients -= 1
    50. Me.BeginInvoke(Sub()
    51. RemoteMenu.lb_clients.Text = connectedClients.ToString & " Benutzer verbunden"
    52. Debug.WriteLine("Remote User abgemeldet")
    53. clients.Remove(clients.Item(clients.Count - 1))
    54. End Sub)
    55. Exit While
    56. End If
    57. Dim encoder As New ASCIIEncoding()
    58. Dim msg As String = encoder.GetString(message, 0, bytesRead)
    59. Dim cleanmsg As String = msg.Substring(4)
    60. RemoteHandler(cleanmsg) 'Verarbeitet in anderem Sub den Empfangenen Text
    61. Echo(msg, encoder, clientStream)
    62. End While
    63. tcpClient.Close()
    64. End Sub
    65. Private Sub SendMsg(ByVal msg As String)
    66. For Each client As NetworkStream In clients
    67. Dim encoder As New ASCIIEncoding
    68. Dim msg_complette As String = vbNullChar & vbNullChar & vbNullChar & ChrW(msg.Length) & msg
    69. Dim buffer As Byte() = encoder.GetBytes(msg_complette)
    70. client.Write(buffer, 0, buffer.Length)
    71. Next
    72. End Sub
    73. Private Sub Echo(msg As String, encoder As ASCIIEncoding, clientStream As NetworkStream)
    74. Dim buffer As Byte() = encoder.GetBytes(msg)
    75. clientStream.Write(buffer, 0, buffer.Length)
    76. clientStream.Flush()
    77. End Sub
    78. #End Region


    Liebe Grüße
    sothere
    Fein!

    Wenn ich recht verstehe sind die Streams von Phone.StreamSocket direkt kompatibel mittm NetworkStream der Desktop-Entwicklung.

    Nur die Methode PhoneClient.StartListening() würde ich anders benennen.
    Listening ist in meiner Welt Aufgabe eines TcpListeners, also des Servers. Ein Listener akzeptiert Connection-Anfragen.
    Ein Client listened nicht, sondern er connected sich und received dann Data (falls der Listener im Server ihn accepted hat).

    Es sei denn, du hast eine ganz andere Netz-Struktur, wo man evtl. garnimmer klar zw. Servern und Clients unterscheidet.

    Edit:
    Naja, wenn ich StartListening() länger angucke, finde ich sie immer mehr "zusammengeschustert" (ist dir eiglich klar, wie diskriminierend dieser Begriff ist ? ;) ).
    Schon dass die Methode Async ist, aber garnet Awaited aufgerufen wird riecht mir sehr faul.
    Und was bei den beiden Returns dann passieren wird scheint mir ebenfalls recht abenteuerlich - vermutlich sind die Returns einfach noch garnet aufgetreten in den bisherigen Tests.

    Aber genaues weiß ich nicht, ich kanns ja nicht testen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Oh, hast recht! Das sind noch Altlasten, hab ich jetzt entfernt :D Der Code war in der Tat ein bisschen "zusammengeschustert", da ich schlicht und ergreifend nirgends eine sinnvolle Dokumentation für beide Seiten gefunden hatte. Also musste ich die Phone App versuchen an meinen schon vorhandenen Servercode anzupassen.
    Hab das ganze auch umbenannt! Danke für die Tipps.
    Liebe Grüße
    sothere