Kommunikation PHP <-> VB.net

  • PHP

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Igel.

    Kommunikation PHP <-> VB.net

    Hallo zusammen,

    ich programmiere gerade eine Windows-Forms-Anwendung (nachfolgend "ServerManager" genannt), die auf einem Root-Server laufen soll, und Game-Server starten, stoppen und updaten soll - soweit so gut. Das eigentliche Ziel ist allerdings, den ServerManager über einen Webserver (php) fernzusteuern. ServerManager und Webserver laufen auf dem gleichen Server.
    Ich habe bereits mit einem TCP-Socket "experimentiert" und zunächst ein IRC (Server + Client) mit einem Tutorial programmiert. Somit habe ich neben dem ServerManager, der als Server arbeiten soll, auch einen Client, mit dem ich testen kann. Die Kommunikation zwischen dem ServerManager und dem IRC-Client funktioniert soweit auch. Der Listener läuft im Hintergrund, sodass die Bedienung der Oberfläche nicht beeinträchtig wird.

    Das hier ist mein VB-net Code, mit dem die Kommunikation läuft:

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.IO
    3. Imports System.Net
    4. Imports System.Net.Sockets
    5. Imports System.Threading
    6. Public Class TCPControl
    7. Public Event MessageReceived(sender As TCPControl, Data As String)
    8. ' SERVER CONFIG
    9. Public TCPServerIP As IPAddress = IPAddress.Parse("127.0.0.1")
    10. Public TCPServerPort As Integer = 4305
    11. Public TCPServer As TcpListener
    12. Private CommThread As Thread
    13. Private IsActivated As Boolean = True
    14. ' CLIENT
    15. Private Client As TcpClient
    16. Private ClientData As StreamReader
    17. Public Sub New()
    18. TCPServer = New TcpListener(TCPServerIP, TCPServerPort)
    19. TCPServer.Start()
    20. CommThread = New Thread(New ThreadStart(AddressOf Listening))
    21. CommThread.Start()
    22. End Sub
    23. Public Sub StartServer()
    24. IsActivated = True
    25. End Sub
    26. Public Sub StopServer()
    27. IsActivated = False
    28. End Sub
    29. Private Sub Listening()
    30. ' CREATE LISTENER LOOP
    31. Do Until IsActivated = False
    32. ' ACEPT INCOMING CONNECTIONS
    33. If TCPServer.Pending = True Then
    34. Client = TCPServer.AcceptTcpClient
    35. ClientData = New StreamReader(Client.GetStream)
    36. End If
    37. ' RAISE EVENT FOR INCOMING MESSAGES
    38. If ClientData IsNot Nothing Then
    39. Try
    40. RaiseEvent MessageReceived(Me, ClientData.ReadLine)
    41. Catch ex As Exception
    42. Console.WriteLine(ex.Message)
    43. End Try
    44. End If
    45. ' REDUCE CPU USAGE
    46. Thread.Sleep(100)
    47. Loop
    48. End Sub
    49. Sub SendToClient(ByVal Data As Object, Optional ByVal SilentMode As Boolean = False)
    50. If IsActivated = True Then
    51. Try
    52. Dim TX As New StreamWriter(Client.GetStream)
    53. TX.WriteLine(Data.ToString)
    54. TX.Flush()
    55. Catch ex As Exception
    56. If SilentMode = False Then MsgBox("SendToClient:" & vbCrLf & ex.Message)
    57. End Try
    58. End If
    59. End Sub
    60. End Class


    und der dazugehörige Code im Hauptform:

    VB.NET-Quellcode

    1. Public Class Mainfrm
    2. Private TCPServer As TCPControl
    3. Private Delegate Sub UpdateTextDelegate(RTB As RichTextBox, txt As String)
    4. Private Sub Mainfrm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5. TCPServer = New TCPControl
    6. AddHandler TCPServer.MessageReceived, AddressOf OnLineReceived
    7. TCPServer.StartServer()
    8. '...
    9. end sub
    10. ' UPDATE TEXTBOX
    11. Private Sub UpdateText(RTB As RichTextBox, txt As String)
    12. If RTB.InvokeRequired Then
    13. RTB.Invoke(New UpdateTextDelegate(AddressOf UpdateText), New Object() {RTB, txt})
    14. Else
    15. If txt IsNot Nothing Then RTB.AppendText("[" & Format(Now, "dd.MM.yyyy HH:mm:ss") & "] " & txt & vbCrLf)
    16. End If
    17. End Sub
    18. Private Sub OnLineReceived(sender As TCPControl, Data As String)
    19. UpdateText(TaReceive, Data)
    20. ValidateRequestAndRespond(Data)
    21. End Sub
    22. ' ...
    23. end class


    Die Probleme fangen nun mit dem Webserver an.
    Hier zunächst mal der (Test-)Code, mit dem ich das Ganze versucht habe:

    PHP-Quellcode

    1. <?php
    2. echo '<form method="post" action="./test.php">
    3. <input type="text" name="command" size="40">&nbsp;<input type="submit" name="submit" value="senden"><br>
    4. <input type="checkbox" name="readresponse" value="1"> Antwort einlesen
    5. </form>';
    6. if(isset($_POST['submit'])) {
    7. if($_POST['command'] != '') {
    8. $address = '127.0.0.1';
    9. $service_port = '4305';
    10. $in = $_POST['command'];
    11. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    12. if ($socket === false) {
    13. echo "socket_create() fehlgeschlagen: Grund: " . socket_strerror(socket_last_error()) . "<br>";
    14. } else {
    15. echo "OK.<br>";
    16. }
    17. echo "Versuche, zu '$address' auf Port '$service_port' zu verbinden ...<br>";
    18. $result = socket_connect($socket, $address, $service_port);
    19. if ($result === false) {
    20. echo "socket_connect() fehlgeschlagen.<br>Grund: ($result) " . socket_strerror(socket_last_error($socket)) . "<br>";
    21. } else {
    22. echo "OK.<br>";
    23. }
    24. echo "Sending command '".$in."'<br>";
    25. socket_write($socket, $in, strlen($in));
    26. echo "OK.<br><br>";
    27. echo "Socket schließen ...<br>";
    28. socket_close($socket);
    29. echo "OK.<br><br>";
    30. if(isset($_POST['readresponse'])) {
    31. echo '<hr><br>';
    32. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    33. if ($socket === false) {
    34. echo "socket_create() fehlgeschlagen: Grund: " . socket_strerror(socket_last_error()) . "<br>";
    35. } else {
    36. echo "OK.<br>";
    37. }
    38. echo "Versuche, zu '$address' auf Port '$service_port' zu verbinden ...<br>";
    39. $result = socket_connect($socket, $address, $service_port);
    40. if ($result === false) {
    41. echo "socket_connect() fehlgeschlagen.<br>Grund: ($result) " . socket_strerror(socket_last_error($socket)) . "<br>";
    42. } else {
    43. echo "OK.<br>";
    44. }
    45. echo "Reading Response...<br>";
    46. $buf = socket_read ($socket, 2048, PHP_NORMAL_READ);
    47. echo 'Antwort: '.$buf.'<br><br>';
    48. echo "Socket schließen ...<br>";
    49. socket_close($socket);
    50. echo "OK.<br><br>";
    51. }
    52. ?>


    Das Senden vom Webserver an den ServerManager klappt soweit auch. Allerdings stelle ich fest, dass wenn ich einmalig etwas vom Webserver an meinen IRC-Server sende, sich die Nachricht scheinbar ständig wiederholt wird (Ausgabe erfolgt in Textfeld, hier werden immer neue Zeilen erzeugt, beim Senden über den IRC-Client passiert das nicht).
    Das ist schon mal das erste Fragezeichen.. ?(

    Sobald ich im php-Skript die Antwort auslesen will, die von der Anwendung auch gesendet wird, scheint er nichts zu bekommen, und "läd" ewig die Seite weiter..
    Hier verstehe ich nicht, warum hier nichts ankommt.. ?(

    Das beides auf einer Kiste läuft, sollten Firewalls und so, keinen Einfluss darauf haben.

    Kann mir hier jemand weiterhelfen, ich hab überhaupt keine Ahnung mehr, woran das liegen könnte... :(

    Danke für eure Hilfe!

    cya Igel

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

    Moin,

    wenn du nach deinem Command die Antwort davon haben willst warum schließt du denn dann die Verbindung und öffnest wieder?
    Du musst natürlich nachdem Senden dann die Antwort auswerten, ohne schließen und öffnen das funktioniert nicht.

    Siehe dir dazu mal die Beispiele im PHP Manual an: php.net/manual/de/sockets.examples.php

    Zu dem Problem mit den doppelten Commands da sehe ich hier in dem Code nun nichts von.
    Grüße , xChRoNiKx

    Nützliche Links:
    Visual Studio Empfohlene Einstellungen | Try-Catch heißes Eisen
    Danke für deine Antwort.

    Das mit dem schließen und nochmaligen Öffnen der Verbindung hab ich gemacht, weil es anders auch nicht funktioniert hat.
    Ursprünglich sah das so aus:

    PHP-Quellcode

    1. <?php
    2. echo '<form method="post" action="./test.php">
    3. <input type="text" name="command" size="40">&nbsp;<input type="submit" name="submit" value="senden"><br>
    4. <input type="checkbox" name="readresponse" value="1"> Antwort einlesen
    5. </form>';
    6. if(isset($_POST['submit'])) {
    7. if($_POST['command'] != '') {
    8. $address = '127.0.0.1';
    9. $service_port = '4305';
    10. $in = $_POST['command'];
    11. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    12. if ($socket === false) {
    13. echo "socket_create() fehlgeschlagen: Grund: " . socket_strerror(socket_last_error()) . "<br>";
    14. } else {
    15. echo "OK.<br>";
    16. }
    17. echo "Versuche, zu '$address' auf Port '$service_port' zu verbinden ...<br>";
    18. $result = socket_connect($socket, $address, $service_port);
    19. if ($result === false) {
    20. echo "socket_connect() fehlgeschlagen.<br>Grund: ($result) " . socket_strerror(socket_last_error($socket)) . "<br>";
    21. } else {
    22. echo "OK.<br>";
    23. }
    24. echo "Sending command '".$in."'<br>";
    25. socket_write($socket, $in, strlen($in));
    26. echo "OK.<br><br>";
    27. echo "Reading Response...<br>";
    28. $buf = socket_read ($socket, 2048, PHP_NORMAL_READ);
    29. echo 'Antwort: '.$buf.'<br><br>';
    30. echo "Socket schließen ...<br>";
    31. socket_close($socket);
    32. echo "OK.<br><br>";
    33. ?>


    xChRoNiKx schrieb:

    Zu dem Problem mit den doppelten Commands da sehe ich hier in dem Code nun nichts von.

    Genau das ist ja das Problem, laut dem php-Code wird ja auch nur einmal gesendet.. Ich hatte überlegt, ob das TCP-Paket vielleicht nicht bestätigt und deshalb widerholt wird..

    cya Igel

    Du meinst, so ne Art Mini-Webserver im ServerManager?
    Das Webinterface soll schon komplexer ausfallen, mit einer kompletten Benutzerverwaltung mit MySQL-Datanbank usw, das würde ich auch gerne dort lassen, zumal ich einige Module schon dafür in php habe.

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

    So, ich hab jetzt noch ein bisschen rum getestet und habe einen TCP-Server und -Client in VB.net, als auch in php. Beides (Senden und Empfangen) geht, solange ich innerhalb einer Programmiersprache bleibe. Nur wenn ich von php zu VB.net was schicken will, funktioniert es nicht.

    Hier mal der VB.net-Quellcode:
    TCP-Class:

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.IO
    3. Imports System.Net
    4. Imports System.Net.Sockets
    5. Imports System.Text
    6. Imports System.Threading
    7. Public Class TCPControl
    8. Public Event MessageReceived(sender As TCPControl, Data As String)
    9. ' SERVER CONFIG
    10. Public ServerIP As IPAddress = IPAddress.Parse("127.0.0.1")
    11. 'Public ServerIP As IPAddress = IPAddress.Any
    12. Public ServerPort As Integer = 4305
    13. Public TCPServer As TcpListener
    14. Private TCPCommThread As Thread
    15. Private IsActivated As Boolean = True
    16. ' CLIENT
    17. Private Client As TcpClient
    18. Private ClientData As StreamReader
    19. Public Sub New()
    20. TCPServer = New TcpListener(ServerIP, ServerPort)
    21. TCPServer.Start()
    22. TCPCommThread = New Thread(New ThreadStart(AddressOf TCPListening))
    23. TCPCommThread.Start()
    24. End Sub
    25. Public Sub StartServer()
    26. IsActivated = True
    27. End Sub
    28. Public Sub StopServer()
    29. IsActivated = False
    30. End Sub
    31. Private Sub TCPListening(Optional ByVal SilentMode As Boolean = True)
    32. ' CREATE LISTENER LOOP
    33. Do Until IsActivated = False
    34. ' ACCEPT INCOMING CONNECTIONS
    35. If TCPServer.Pending = True Then
    36. Client = TCPServer.AcceptTcpClient
    37. ClientData = New StreamReader(Client.GetStream)
    38. End If
    39. ' RAISE EVENT FOR INCOMING MESSAGES
    40. Do While IsActivated
    41. Try
    42. RaiseEvent MessageReceived(Me, ClientData.ReadLine)
    43. Catch IOEx As IO.IOException
    44. Console.WriteLine(IOEx.Message)
    45. Exit Do
    46. Catch NREx As NullReferenceException
    47. Console.WriteLine(NREx.Message)
    48. Exit Do
    49. End Try
    50. Loop
    51. ' REDUCE CPU USAGE
    52. Thread.Sleep(100)
    53. Loop
    54. End Sub
    55. Sub SendToClient(ByVal Data As Object)
    56. If IsActivated = True Then
    57. Try
    58. Dim TX As New StreamWriter(Client.GetStream)
    59. TX.WriteLine(Data.ToString & "\r\n")
    60. TX.Flush()
    61. Catch ex As Exception
    62. Console.WriteLine(ex.Message)
    63. End Try
    64. End If
    65. End Sub
    66. End Class


    Anwendung:

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.IO
    3. Imports System.Net
    4. Imports System.Net.Sockets
    5. Imports System.Text
    6. Imports System.Text.RegularExpressions
    7. Public Class Hauptfenster
    8. Private TCPServer As TCPControl
    9. Private Delegate Sub UpdateTextDelegate(RTB As RichTextBox, txt As String)
    10. Private Sub Hauptfenster_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    11. CheckForIllegalCrossThreadCalls = False
    12. TCPServer = New TCPControl
    13. AddHandler TCPServer.MessageReceived, AddressOf OnLineReceived
    14. TCPServer.StartServer()
    15. End Sub
    16. Private Sub Hauptfenster_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    17. TCPServer.StopServer()
    18. End Sub
    19. ' --------------------------------------------------------------------------------------------------------------------
    20. ' --------- TCP VERBINDUNG -------------------------------------------------------------------------------------------
    21. ' --------------------------------------------------------------------------------------------------------------------
    22. ' UPDATE TEXTBOX
    23. Private Sub UpdateText(RTB As RichTextBox, txt As String)
    24. If RTB.InvokeRequired Then
    25. RTB.Invoke(New UpdateTextDelegate(AddressOf UpdateText), New Object() {RTB, txt})
    26. Else
    27. If txt IsNot Nothing Then RTB.AppendText("[" & Format(Now, "dd.MM.yyyy HH:mm:ss") & "] " & txt & vbCrLf)
    28. End If
    29. End Sub
    30. Private Sub OnLineReceived(sender As TCPControl, Data As String)
    31. UpdateText(TaReceive, Data)
    32. TCPServer.SendToClient(Data)
    33. End Sub
    34. End Class


    Und hier der php-Quellcode:
    Server:

    PHP-Quellcode

    1. // set some variables
    2. $host = "127.0.0.1";
    3. $port = 4305;
    4. // don't timeout!
    5. set_time_limit(0);
    6. // create socket
    7. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Could not create socket\n");
    8. // bind socket to port
    9. $result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");
    10. // start listening for connections
    11. $result = socket_listen($socket, 3) or die("Could not set up socket listener\n");
    12. // accept incoming connections
    13. // spawn another socket to handle communication
    14. $spawn = socket_accept($socket) or die("Could not accept incoming connection\n");
    15. // read client input
    16. $input = socket_read($spawn, 1024) or die("Could not read input\n");
    17. // clean up input string
    18. $input = trim($input);
    19. echo "Client Message: ".$input;
    20. // reverse client input and send back
    21. $output = strrev($input) . "\n";
    22. socket_write($spawn, $output, strlen ($output)) or die("Could not write output\n");
    23. // close sockets
    24. socket_close($spawn);
    25. socket_close($socket);


    Client:

    PHP-Quellcode

    1. $host = '127.0.0.1';
    2. $port = 4305;
    3. $message = "Hello Server";
    4. echo "Message To server: ".$message;
    5. // create socket
    6. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Could not create socket\n");
    7. // connect to server
    8. $result = socket_connect($socket, $host, $port) or die("Could not connect to server\n");
    9. // send string to server
    10. socket_write($socket, $message, strlen($message)) or die("Could not send data to server\n");
    11. // get server response
    12. $result = socket_read ($socket, 1024, PHP_NORMAL_READ) or die("Could not read server response\n");
    13. echo "<br><br>Reply From Server: ".$result;
    14. echo '<br>Last error: ['.socket_last_error().'] '.socket_strerror(socket_last_error());
    15. // close socket
    16. socket_close($socket);


    Werden die Daten irgendwie unterschiedlich übertragen, sodass die sich gegenseitig nicht verstehen (wobei das ja eigentlich nicht sein kann, ist ja das gleiche Protokoll...)????

    cya Igel
    Ok, ich habe mittlerweile im Internet ein Tutorial gefunden, das in C# genau das macht, was ich gesucht habe.
    Hier der Code:

    TCP-Class:

    VB.NET-Quellcode

    1. Option Strict On
    2. 'Imports System.IO
    3. Imports System.Net
    4. Imports System.Net.Sockets
    5. Imports System.Text
    6. Imports System.Threading
    7. Public Class TCPControl
    8. Public Event MessageReceived(sender As TCPControl, Data As String)
    9. Private ServerIP As IPAddress
    10. Private TCPServer As TcpListener
    11. Private TCPCommThread As Thread
    12. Private IsActivated As Boolean = True
    13. Private Response As String = ""
    14. Public Sub New(IP As String, Port As Integer)
    15. ServerIP = IPAddress.Parse(IP)
    16. TCPServer = New TcpListener(ServerIP, Port)
    17. TCPCommThread = New Thread(New ThreadStart(AddressOf TCPListening)) With {.IsBackground = True}
    18. TCPCommThread.Start()
    19. End Sub
    20. Public Sub StartServer()
    21. IsActivated = True
    22. End Sub
    23. Public Sub StopServer()
    24. IsActivated = False
    25. End Sub
    26. Public Function ServerStatus() As Boolean
    27. Return IsActivated
    28. End Function
    29. Private Sub TCPListening(Optional ByVal SilentMode As Boolean = True)
    30. 'Console.WriteLine("IsActivated: " & IsActivated)
    31. If IsActivated = True Then
    32. Try
    33. TCPServer.Start()
    34. Console.WriteLine("The server is running at port 4305.")
    35. Console.WriteLine("The local End point is: " & TCPServer.LocalEndpoint.ToString)
    36. Console.WriteLine("Waiting for a connection..")
    37. While IsActivated
    38. Dim TCPsocket As Socket = TCPServer.AcceptSocket()
    39. Console.WriteLine("Connection accepted from " & TCPsocket.RemoteEndPoint.ToString)
    40. Dim b As Byte() = New Byte(99) {}
    41. Dim k As Integer = TCPsocket.Receive(b)
    42. Dim TCPRequest As String = Encoding.ASCII.GetString(b.Take(k).ToArray())
    43. Console.WriteLine("Recieved: " & TCPRequest)
    44. RaiseEvent MessageReceived(Me, TCPRequest)
    45. If Response <> "" Then
    46. Dim asen As ASCIIEncoding = New ASCIIEncoding()
    47. TCPsocket.Send(asen.GetBytes(Response))
    48. TCPsocket.Close()
    49. Console.WriteLine("Sent: " & Response)
    50. Response = ""
    51. End If
    52. Thread.Sleep(100)
    53. End While
    54. TCPServer.[Stop]()
    55. Catch ex As Exception
    56. Console.WriteLine("Error: " & ex.StackTrace)
    57. End Try
    58. End If
    59. End Sub
    60. Public Sub SendToClient(ByVal text As String)
    61. If IsActivated = True Then
    62. Response = text
    63. End If
    64. End Sub
    65. End Class


    php-Client:

    PHP-Quellcode

    1. error_reporting(E_ALL);
    2. ini_set("display_errors", 1);
    3. $address="127.0.0.1";
    4. $service_port = 4305;
    5. echo '<form method="post" action="./test2.php">
    6. <input type="text" name="command" size="40">&nbsp;<input type="submit" name="submit" value="senden">
    7. </form>';
    8. if(isset($_POST['submit'])) {
    9. if($_POST['command'] != '') {
    10. /* Create a TCP/IP socket. */
    11. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    12. if ($socket === false) {
    13. echo "socket_create() failed: reason: <br>" .
    14. socket_strerror(socket_last_error()) . "\n";
    15. }
    16. echo "Attempting to connect to '$address' on port '$service_port'...<br>";
    17. $result = socket_connect($socket, $address, $service_port);
    18. if ($result === false) {
    19. echo "socket_connect() failed.\nReason: ($result) <br>" .
    20. socket_strerror(socket_last_error($socket)) . "\n";
    21. }else {
    22. echo "connected<br>";
    23. }
    24. $in = $_POST['command'];
    25. $out = '';
    26. echo "Client Sent: PING !<br>";
    27. socket_write($socket, $in, strlen($in));
    28. echo "SENT!\n<br>";
    29. echo "Reading response: <em>";
    30. while ($out = socket_read($socket, 2048)) {
    31. echo $out;
    32. }
    33. echo '</em>';
    34. socket_close($socket);
    35. }
    36. }


    Vielleicht hilft das dem ein oder anderen. ;)

    cya Igel