Laden...

PHP-Script soll mit Consolen-Anwendung kommunizieren

Erstellt von NewCannon vor 9 Jahren Letzter Beitrag vor 9 Jahren 3.759 Views
N
NewCannon Themenstarter:in
16 Beiträge seit 2012
vor 9 Jahren
PHP-Script soll mit Consolen-Anwendung kommunizieren

Guten Abend,

ich habe mir eine kleine Consolen Anwendung geschrieben die mithilfe einiger Befehle Dienste auf dem System steuert.

Nun möchte ich diese Anwendung aber auch von Außerhalb wie eines PHP Skripts ansprechen und die Anwendung soll auch eine Statusmeldung zurückliefern.

Ich hab das ganze mit TCP/IP versucht allerdings bekommt das PHP Skript immer einen Timeout, welche möglichkeiten gäbe es denn noch um ein PHP Skript mit einer Consolen Anwendung Kommunizieren zu lassen wo es auch möglich ist dem Skript direkt einen Status oder eine Meldung zurückzuliefern außer via TCP/IP.

Gibt es da nicht irgendwie was mit XML/RPC oder irgendwie sowas?

Danke für eure Hilfe.

Gruß
Patrcik

6.911 Beiträge seit 2009
vor 9 Jahren

Hallo NewCannon,

grundsätzlich ist da jeder Art der IPC (inter-process-communication) möglich. Hier würde sich WCF anbieten und zwar so, dass die Consolen-Anwendung als Host für den Service fungiert. Das PHP-Script wäre demnach der Client.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

U
1.688 Beiträge seit 2007
vor 9 Jahren

Hallo,

TCP/IP muss prinzipiell funktionieren. Tut es das nicht, gibt's noch ein systematisches, aber kein grundsätzliches Problem.

N
NewCannon Themenstarter:in
16 Beiträge seit 2012
vor 9 Jahren

WCF scheint für mich die passende Lösung zu sein. Allerdings finde ich in Visual Studio 2013 Desktop Edition den WCF Service nicht.

6.911 Beiträge seit 2009
vor 9 Jahren

Hallo NewCannon,

meinst du die Projekt-Vorlage oder was? Das ist nicht (unbedingt) nötig. Füge bei deinem bestehen Consolen-Projekt einfach einen Verweis zu System.ServiceModel hinzu und schreib den Code für WCF wie du ihn sicherlich schon gesehen hast.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

N
NewCannon Themenstarter:in
16 Beiträge seit 2012
vor 9 Jahren

So, habe mich nun mal dran gesetzt den WCF Host zu erstellen gab soweit auch keine Problme ich habe den Code:


using(ServiceHost host = new ServiceHost(typeof(WittyBots_Service.BotHost)))
{
    host.Open();
    Console.WriteLine("Service Host started!");
}

Die App.config schaut so aus:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <system.serviceModel>
    <services>
      <service name="WittyBots_Service.BotHost" behaviorConfiguration="maxBehavior">
        <endpoint address="BotService" binding="basicHttpBinding" contract="WittyBots_Service.IBotHost"></endpoint>
        <endpoint  address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>

        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="maxBehavior">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Er gibt mir in der Console auch Service Host started aus aber wen ich nun im Browser die Adresse localhost:8080 eingebe unter der ich den Service gestartet habe bekomme ich keine Service Webseite angezeigt wie ich es in einigen Tutorials über WCF gesehen habe. Mein Browser sagt nur ich habe kein Zugriff auf das Netzwerk.

Sind die Tutorials einfach nur veraltet und diese Service Webseite wird nicht mehr angezeigt in den neuen WCF Versionen oder habe ich einen Fehler in meinem Code?

6.911 Beiträge seit 2009
vor 9 Jahren

Hallo NewCannon,

probier die Adresse http://localhost:8080/BotService - auf dieser ist das Http-Binding deklariert. Nur unter localhost:8080 läuft ja nix.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

N
NewCannon Themenstarter:in
16 Beiträge seit 2012
vor 9 Jahren

Leider kommt dort auch nix auch wen ich in einem Client Programm die adresse http://localhost:8080/BotService als Dienstverweis hinzufügen möchte kommt ein Fehler:

Fehlermeldung:
Fehler bei dem Versuch, Dienste unter "http://localhost:8080/BotService" zu finden.

6.911 Beiträge seit 2009
vor 9 Jahren

Hallo NewCannon,

kannst du dein Projekt hier anhängen, dann schau ich es mir mal an.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

N
NewCannon Themenstarter:in
16 Beiträge seit 2012
vor 9 Jahren

Das Archiv ist leider zu Groß zum Anhängen, daher habe ich es auf meinem Server hochgeladen: http://softwareelite.de/WittyBots.rar

N
NewCannon Themenstarter:in
16 Beiträge seit 2012
vor 9 Jahren

Hab das ganze nun auch schonn mit Sockets probiert auch das funktioniert nicht erhalte immer ein Timeout der Server code schaut dabei so aus:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Premium_Bots
{
    class Program
    {
        private static Socket sListener;
        private static SocketPermission permission;
        private static IPEndPoint ipEndPoint;
        private static Socket handler;

        static void Main(string[] args)
        {
            permission = new SocketPermission(NetworkAccess.Accept, TransportType.Tcp, "", SocketPermission.AllPorts);
            IPHostEntry ipHost = Dns.GetHostEntry("");
            IPAddress ipAddr = ipHost.AddressList[0];
            ipEndPoint = new IPEndPoint(ipAddr, 4510);  
            sListener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            sListener.Bind(ipEndPoint);
            sListener.Listen(5);
            AsyncCallback aCallback = new AsyncCallback(AcceptCallback);
            sListener.BeginAccept(aCallback, sListener);
            Console.ReadLine();
        }

        public static void AcceptCallback(IAsyncResult ar)
        {
            Socket listener = null;

            // A new Socket to handle remote host communication 
            Socket handler = null;

            try
            {
                // Receiving byte array 
                byte[] buffer = new byte[1024];
                // Get Listening Socket object 
                listener = (Socket)ar.AsyncState;
                // Create a new socket 
                handler = listener.EndAccept(ar);

                // Using the Nagle algorithm 
                handler.NoDelay = false;

                // Creates one object array for passing data 
                object[] obj = new object[2];
                obj[0] = buffer;
                obj[1] = handler;

                // Begins to asynchronously receive data 
                handler.BeginReceive(
                    buffer,        // An array of type Byt for received data 
                    0,             // The zero-based position in the buffer  
                    buffer.Length, // The number of bytes to receive 
                    SocketFlags.None,// Specifies send and receive behaviors 
                    new AsyncCallback(ReceiveCallback),//An AsyncCallback delegate 
                    obj            // Specifies infomation for receive operation 
                    );

                // Begins an asynchronous operation to accept an attempt 
                AsyncCallback aCallback = new AsyncCallback(AcceptCallback);
                listener.BeginAccept(aCallback, listener);
            }
            catch (Exception exc) {  }
        }

        public static void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                // Fetch a user-defined object that contains information 
                object[] obj = new object[2];
                obj = (object[])ar.AsyncState;

                // Received byte array 
                byte[] buffer = (byte[])obj[0];

                // A Socket to handle remote host communication. 
                handler = (Socket)obj[1];

                // Received message 
                string content = string.Empty;


                // The number of bytes received. 
                int bytesRead = handler.EndReceive(ar);

                if (bytesRead > 0)
                {
                    content += Encoding.Unicode.GetString(buffer, 0,
                        bytesRead);

                    // If message contains "<Client Quit>", finish receiving
                    if (content.IndexOf("<Client Quit>") == -1)
                    {
                        // Continues to asynchronously receive data
                        byte[] buffernew = new byte[1024];
                        obj[0] = buffernew;
                        obj[1] = handler;
                        handler.BeginReceive(buffernew, 0, buffernew.Length,
                            SocketFlags.None,
                            new AsyncCallback(ReceiveCallback), obj);
                    }

                    Console.WriteLine(content);
                }
            }
            catch (Exception exc) {  }
        }
    }
}

Der PHP Client:

<?php
$host = "81.20.133.51";
$port = "4510";
$timeout = 15;  //timeout in seconds

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
or die("Unable to create socket\n");

socket_set_nonblock($socket)
or die("Unable to set nonblock on socket\n");

$time = time();
while (!@socket_connect($socket, $host, $port))
{
	$err = socket_last_error($socket);
	if ($err == 115 || $err == 114)
	{
		if ((time() - $time) >= $timeout)
		{
			socket_close($socket);
			die("Connection timed out.\n");
		}
		sleep(1);
		continue;
	}
	die(socket_strerror($err) . "\n");
}

socket_set_block($this->socket)
or die("Unable to set block on socket\n");
?>

Kann jemand weiterhelfen?

5.658 Beiträge seit 2006
vor 9 Jahren

Hi NewCannon,

ein guter Ansatzpunkt wäre ja, mal die Exceptions auf der .NET-Seite auszuwerten, anstatt sie einfach zu ignorieren.

Christian

Weeks of programming can save you hours of planning

N
NewCannon Themenstarter:in
16 Beiträge seit 2012
vor 9 Jahren

Habe ich versucht aber scheinbar kommt nix an die Consolenanwendung durch

W
955 Beiträge seit 2010
vor 9 Jahren

Dann schreib die Exceptions doch in das EreignisLog des Servers statt sie zu verwerfen.

185 Beiträge seit 2005
vor 9 Jahren

Hast du mal versucht, dich mit deinem Server mit Telnet bzw. Putty zu verbinden?
Bekommst du eine Verbindung, was sagt der Debugger?
Auf welche IP-Adresse bindest du?