Kommunikation mit einem c-Prozess funzt nicht richtig

Status
Nicht offen für weitere Antworten.

horstboehse

Mitglied
Hallo!

Ich habe ein Problem bei der Kommunikation mit einem aus Java heraus gestarteten Prozess über die Standardein- und ausgabe. Ich weiß, dass es dazu in diesem Forum eine Menge Beiträge gibt und ich habe mich schon durch sehr viel durchgewühlt. Leider löst keiner dieser Beiträge mein Problem.

Also, zu meinem Problem:

Ich habe ein kleines Testprogramm geschrieben, das einen Prozess startet. Anschließend holt es sich die Standardein- und ausgabestreams dieses Prozesses und startet 2 Hintergrundthreads. Einer fragt ständig den Inputstream ab, der andere den Errorstream. Aus Performancegründen habe ich Wartezeiten von 10ms eingebaut. Die Ergebnisse schreiben die Threads in ein Textfeld.

Über einen Send-Button wird andererseits ein String an den Outpustream des Prozesses gesendet. Auf diese Weise will ich mit dem Prozess kommunizieren.

Als Prozess habe ich mir in C 3 kleine Testprozesse geschrieben, bei denen das Javaprogramm stets unterschiedlich reagiert:

1. Der Prozess gibt in einer Endlosschleife etwas in die Standardausgabe aus.

Bei diesem Prozess funktioniert es, wie es soll. D.h. die Ausgabe des Prozesses erscheint im Textfeld der
Javaanwendung. Aufgrund der Endlosschleife ist der Prozessor natürlich voll ausgelastet

2. Wie bei 1., nur dass hier in jeder Iteration ein Sleep(11) eingebaut ist, so dass der Prozess nicht so viele
Ressourcen schluckt.

Hier funktioniert es leider nicht. Die Ausgabe des Prozesses erscheint nicht in dem Textfeld.

3. Dieser Prozess wartet auf eine Eingabe von der Standardeingabe. Anschließend wird ein Beep-Ton ausgegeben und
danach wird etwas auf der Standardausgabe ausgegeben. Dies passiert ebenfalls in einer Schleife.

Hier funktioniert nur das Senden an den Prozess. Denn nach dem Betätigen von "Send" ertönt der Beep-Ton. Es
erscheint jedoch keine Ausgabe im Textfeld.


Ich bin mit meinem Latein am Ende und weiß leider nicht mehr, woran es liegen könnte. Vielleicht kann mir ja jemand helfen.

Hier ein wenig Code:

Code:
public class Prozesstest 
extends JFrame
{
	
	//Textfelder für Ein- und Ausgabe
	JTextArea InputText;
	JTextField OutputText;
	
	//Prozess- und Threadvariablen
	Process proc;
	InputThread inputthread;
	InputThread errorthread;
	
	//Streams zur Kommunikation mit dem Prozess
	BufferedReader input;
	BufferedReader error;
	PrintStream output;
	
	public Prozesstest()
	{
		//GUI bauen
		super("Prozesstest");
		setLocation(200,200);
		setSize(640,480);
		setVisible(true);
		
		Container CPane = getContentPane();
		CPane.setLayout(new FlowLayout(FlowLayout.LEFT));
		
		//Inputextfeld bauen, scrollbar
		InputText = new JTextArea(20,55);
		JScrollPane scroll = new JScrollPane(InputText);
		//InputText.setBorder(BorderFactory.createEtchedBorder());
		CPane.add(scroll);
		
		//Outputtextfeld bauen
		OutputText = new JTextField(55);
		OutputText.setBorder(BorderFactory.createEtchedBorder());
		CPane.add(OutputText);
		
		//Button zum Senden an den Prozess
		JButton button = new JButton("Send");
		button.addActionListener(new Event());
		CPane.add(button);
		
		CPane.doLayout();
		
		addWindowListener(new WindowClosingAdapter());
	}
	
	public void StartProcess(String cmd)
	{
		try
		{
			//Starten des externen Prozesses
			proc = Runtime.getRuntime().exec(cmd);
			
			//Steams erzeugen
			input = new BufferedReader(new InputStreamReader(proc.getInputStream()));
			error = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
			output = new PrintStream(new BufferedOutputStream(proc.getOutputStream()), true);
			
			//Inputthread starten
			inputthread = new InputThread(input);
			inputthread.run();
			
			//Errorthread starten
			errorthread = new InputThread(error);
			errorthread.run();
			
		}
		catch(IOException e)
		{
			System.out.println("Fehler beim starten des Prozesses");
		}
	
		
	}
	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		//Instanz der Gui erzeugen
		Prozesstest ptest = new Prozesstest();
		
		//Prozess starten
		ptest.StartProcess("TestProzess2.exe");

	}
	
	class WindowClosingAdapter
	extends WindowAdapter
	{
		public void windowClosing(WindowEvent e)
		{
			try
			{
				//Inputthread beenden
				if(inputthread != null) 
				{
					inputthread.interrupt();
					inputthread.join();
				}
				//Errorthread beenden
				if(errorthread != null) 
				{
					errorthread.interrupt();
					errorthread.join();
				}
				//Process zerstören
				if(proc != null)
				{
					proc.destroy();
				}
			}
			catch(Exception ex)
			{
				System.out.println("Fehler beim Schließen");
			}
				
			System.exit(0);
		}
	}
	
	class Event
	implements ActionListener
	{

		@Override
		public void actionPerformed(ActionEvent e) 
		{
			if(e.getActionCommand().equals("Send"))
			{
				try 
				{
					//"hallo" an den Prozess senden
					output.println("hallo");
				} 
				catch (Exception e1) 
				{
					System.out.println("Fehler beim Senden an den Prozess");
				}
			}
		}
		
	}
	
	class InputThread
	extends Thread
	{
		//Zu überwachender Stream
		BufferedReader buffer;
		
		public InputThread(BufferedReader b)
		{
			buffer = b;
		}
		
		public void run()
		{
			try
			{
				//Für immer, wenn der Thread nicht beendet wird
				while(isInterrupted() == false)
				{
					//Solange etwas im Buffer ist und der Thread nicht beendet wird
					while(isInterrupted() == false && buffer.ready())
					{
						//Inhalt im Textfeld ausgeben
						InputText.append(buffer.readLine());
						InputText.append("\n");
						
					}
					
					//10ms warten, wegen der Performance
					sleep(10);
					
				}
				
				//Buffer schließen
				buffer.close();
			}
			catch(Exception e)
			{
				System.out.println("Fehler beim Thread");
			}
		}
	}

}

Danke schonmal im voraus!
 

lhein

Top Contributor
Probier mal bitte folgendes:

Code:
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Prozesstest 
extends JFrame
{
    //Textfelder für Ein- und Ausgabe
    JTextArea InputText;
    JTextField OutputText;
    
    //Prozess- und Threadvariablen
    Process proc;
    InputThread inputthread;
    InputThread errorthread;
    
    //Streams zur Kommunikation mit dem Prozess
    BufferedReader input;
    BufferedReader error;
    PrintStream output;

    boolean isAlive;
    
    public Prozesstest()
    {
        //GUI bauen
        super("Prozesstest");
        setLocation(200,200);
        setSize(640,480);
        setVisible(true);
        
        Container CPane = getContentPane();
        CPane.setLayout(new FlowLayout(FlowLayout.LEFT));
        
        //Inputextfeld bauen, scrollbar
        InputText = new JTextArea(20,55);
        JScrollPane scroll = new JScrollPane(InputText);
        //InputText.setBorder(BorderFactory.createEtchedBorder());
        CPane.add(scroll);
        
        //Outputtextfeld bauen
        OutputText = new JTextField(55);
        OutputText.setBorder(BorderFactory.createEtchedBorder());
        CPane.add(OutputText);
        
        //Button zum Senden an den Prozess
        JButton button = new JButton("Send");
        button.addActionListener(new Event());
        CPane.add(button);
        
        CPane.doLayout();
        
        isAlive = true;
        
        addWindowListener(new WindowClosingAdapter());
    }
    
    public void StartProcess(String cmd)
    {
        try
        {
            //Starten des externen Prozesses
            proc = Runtime.getRuntime().exec(cmd);
            
            //Steams erzeugen
            input = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            error = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
            output = new PrintStream(new BufferedOutputStream(proc.getOutputStream()), true);
            
            //Inputthread starten
            inputthread = new InputThread(input);
            inputthread.run();
            
            //Errorthread starten
            errorthread = new InputThread(error);
            errorthread.run();
            
        }
        catch(IOException e)
        {
            System.out.println("Fehler beim starten des Prozesses");
        }
    
        
    }
    /**
     * @param args
     */
    public static void main(String[] args)
    {
        //Instanz der Gui erzeugen
        Prozesstest ptest = new Prozesstest();
        
        //Prozess starten
        ptest.StartProcess("TestProzess2.exe");

    }
    
    class WindowClosingAdapter
    extends WindowAdapter
    {
        public void windowClosing(WindowEvent e)
        {
            isAlive = false;
 
            try
            {
                //Inputthread beenden
                if(inputthread != null) 
                {
                    inputthread.interrupt();
                    inputthread.join();
                }
                //Errorthread beenden
                if(errorthread != null) 
                {
                    errorthread.interrupt();
                    errorthread.join();
                }
                //Process zerstören
                if(proc != null)
                {
                    proc.destroy();
                }
            }
            catch(Exception ex)
            {
                System.out.println("Fehler beim Schließen");
            }
                
            System.exit(0);
        }
    }
    
    class Event
    implements ActionListener
    {
        public void actionPerformed(ActionEvent e) 
        {
            if(e.getActionCommand().equals("Send"))
            {
                try 
                {
                    //"hallo" an den Prozess senden
                    output.println("hallo");
                } 
                catch (Exception e1) 
                {
                    System.out.println("Fehler beim Senden an den Prozess");
                }
            }
        }
        
    }
    
    class InputThread
    extends Thread
    {
        //Zu überwachender Stream
        BufferedReader buffer;
        
        public InputThread(BufferedReader b)
        {
            buffer = b;
            setDaemon(true);
        }
        
        public void run()
        {
            try
            {
                //Für immer, wenn der Thread nicht beendet wird
                while(isInterrupted() == false && isAlive)
                {
                    // something is readable - so read it
                    String data = "";
                    while (isAlive && (data = buffer.readLine()) != null)
                    {
                        final String line = new String(data);
                        //Inhalt im Textfeld ausgeben
                        SwingUtilities.invokeLater(new Runnable()
                        {
                            public void run()
                            {
                                InputText.append(line);
                                InputText.append("\n");
                                InputText.repaint();
                            }
                        });
                    }
                    
                    //10ms warten, wegen der Performance
                    sleep(10);                    
                }
                
                //Buffer schließen
                buffer.close();
            }
            catch(Exception e)
            {
                System.out.println("Fehler beim Thread");
            }
        }
    }

}

Und stell auch sicher, daß vom C-Prozess immer ein String gefolgt von einem Zeilenumbruch kommt.

lr
 

horstboehse

Mitglied
Danke erstmal für die schnelle Antwort!

Ich habe das jetzt mit deinem Quelltext getestet.

Zunächst dachte ich, dass sie das Problem löst, denn bei dem Prozess, der ständig Ausgaben tätitigt und dazwischen mit Sleep wartet, kam nach einiger Zeit die Ausgabe. Dann habe ich es nochmal mit meiner Quelle getestet und kam zu demselben Ergebnis. Ich hatte wahrscheinlich nur nicht lange genug gewartet.

Dabei wird die Ausgabe immer erst nach ca. 1000 Iterationen des Prozesses auf einmal ausgegeben. Woran liegt das denn? Wird immer zuerst der Puffer vollgeschrieben, bevor etwas ausgelesen werden kann?

Bei dem Prozess, der auf eine Eingabe wartet und erst dann eine Ausgabe tätigt, passiert leider immer noch nichts. Weder bei meiner Quelle, noch bei deiner. :-( Kann es vielleicht sein, dass die Ausgabe hier auch erst nach 1000 Iterationen kommt? Also, wenn ich 1000mal auf "Send" geklickt habe?

Geht das auch irgendwie so, dass ich die Ausgabe direkt empfange?
 

lhein

Top Contributor
Probier mal beim output.println("hallo"); danach ein output.flush(); wenns sowas gibt.

Ansonsten verwendest Du halt einen Reader/Writer der ganze Lines sendet. Wenn Du jedes Zeichen lesen/schreiben willst, dann musst Du einen anderen Writer/Reader bzw. direkt den jeweiligen Stream benutzen.

lr
 

horstboehse

Mitglied
Ich habe das Problem gelöst.

Es lag nicht an Java, sondern am c-Prozess.
Scheinbar wird dort die Standardausgabe auch gepuffert und nur selten geflushed.

Ich habe dort jetzt nach jeder Ausgabe ein fflush(stdout) eingebaut.
Jetzt funktioniert es mit allen 3 Prozessarten tadellos.

Vielen Dank für die Denkanstöße!!
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
CptK Backpropagation parallelisieren: Kommunikation zwischen den Threads Allgemeine Java-Themen 7
L Kommunikation zwischen C# und Java? Allgemeine Java-Themen 5
R PIPE Kommunikation mit Prozess blockiert Allgemeine Java-Themen 0
M Checksummenprüfung bei Client Server kommunikation Allgemeine Java-Themen 3
D Interthread-Kommunikation Allgemeine Java-Themen 6
S Threads Kommunikation zwischen SocketThread und WorkerThread Allgemeine Java-Themen 11
0 Lösungsweg Client Server Kommunikation Fehlermeldung ausgeben Allgemeine Java-Themen 12
L Software-Design: Kommunikation mit SerialPort (RXTX) Allgemeine Java-Themen 2
F Serielle Kommunikation Allgemeine Java-Themen 20
A Kommunikation zwischen 2 Jar-dateien Allgemeine Java-Themen 16
S Kommunikation von Core und GUI über Schnittstellen Allgemeine Java-Themen 2
P Komponenten kommunikation Allgemeine Java-Themen 7
L Serielle Kommunikation Allgemeine Java-Themen 6
G Implementierung einer Kommunikation Allgemeine Java-Themen 7
B SerialPort Kommunikation - Pufferüberlauf Allgemeine Java-Themen 6
0 Sandbox und Applet Kommunikation Allgemeine Java-Themen 9
E kommunikation zwischen Fenstern Allgemeine Java-Themen 3
H Java C++ Interprozess Kommunikation Allgemeine Java-Themen 7
D Klassen Kommunikation Allgemeine Java-Themen 11
M Applet Servlet Kommunikation ein Problem bei externem Server Allgemeine Java-Themen 3
F Kommunikation zw 2 Java-Programmen mit unterschiedl Compiler Allgemeine Java-Themen 13
G Kommunikation mit Remotegeräten Allgemeine Java-Themen 2
A Kommunikation zwischen C++ und Java-Programm Allgemeine Java-Themen 4
J Kommunikation mit USB Gerät, das Midi-Signale sendet Allgemeine Java-Themen 4
G Kommunikation mit der seriellen Schnittstelle Allgemeine Java-Themen 6
C Pattern für Kommunikation gesucht Allgemeine Java-Themen 3
B Kommunikation mit entferntem Thread Allgemeine Java-Themen 6
O kommunikation zw. objekten Allgemeine Java-Themen 7
G Kommunikation von zwei Java-Programmen Allgemeine Java-Themen 3
N Inter-Thread-Kommunikation Allgemeine Java-Themen 3
M Kommunikation mit externem Programm ueber Linux-Pipes Allgemeine Java-Themen 4
M Kommunikation zwischen 2 Programmen Allgemeine Java-Themen 7
G Kommunikation zwischen Threads und Gui Allgemeine Java-Themen 2
T Kommunikation mit batch datei Allgemeine Java-Themen 3
P kommunikation zwischen dialog und threads Allgemeine Java-Themen 4
K MVC - Kommunikation Controller <> Gui Allgemeine Java-Themen 5
P Kommunikation von Threads Allgemeine Java-Themen 5
V Kommunikation zwischen Programmen und Threads Allgemeine Java-Themen 7
H Servlet/Applet Kommunikation Allgemeine Java-Themen 2
C Kommunikation mit USB Port Allgemeine Java-Themen 1
Ernesto95 HTTP Mit JavaScript erzeugte dynamische Webseite auslesen und nach einem Schlüsselwort durchsuchen Allgemeine Java-Themen 6
P Feststellen, Welche Classes ich aus einem JAR nutze? Allgemeine Java-Themen 6
Jose05 mit 2 - 3 Personen an einem Projekt coden Allgemeine Java-Themen 2
M Queue mit einem Array implemetieren Allgemeine Java-Themen 16
8u3631984 Prüfen ob min. ein Element eines Sets in einem anderen Set enh Allgemeine Java-Themen 4
L 2 Dimensionale ListArray Abfrage nach einem Wert suchen Allgemeine Java-Themen 5
melaniemueller Einzelne Zeile aus einer txt Datei in einem String speichern Allgemeine Java-Themen 12
N einem Array Objekte hinzufügen die ihr Array position gespeichert haben Allgemeine Java-Themen 34
Jose05 Speicherung auf einem Server Allgemeine Java-Themen 1
S Folgendes Problem bei einem Programm Allgemeine Java-Themen 1
M Mehrere Ressourcen in einem package ablegen Allgemeine Java-Themen 1
Tobero .jar Dateine aus einem Ordner laden (Java 16) Allgemeine Java-Themen 5
alinakeineAhnungv Hilfe bei einem Straßenbahn-Projekt von mir Allgemeine Java-Themen 18
SaftigMelo In einem Winkel Objekt bewegen Allgemeine Java-Themen 2
Thallius Zeitzone zu einem LocalDate hinzufügen aber ohne es zu ändern... Allgemeine Java-Themen 2
Tobero Meine Funktion für das beinhalten eines Punktes in einem Kreis funktioniert nicht Allgemeine Java-Themen 5
Tobero Wie bekomme ich in welchem Quadrat sich eine Position in einem Grid befindet Allgemeine Java-Themen 11
Noahscript Aus einem byte Array Steuerungszeichen und Code bekommen und ersetzen Allgemeine Java-Themen 3
Kingamadeus2000 Alle mehrfach vorkommenden Buchstaben rekursiv aus einem String entfernen. Allgemeine Java-Themen 6
F Junit Test + Cucumber - JSON auslesen und in einem weiteren Schritt nutzen Allgemeine Java-Themen 0
Zrebna DeleteNode-Funktionalität in einem AVL-Tree Allgemeine Java-Themen 5
pkm Warnungen in einem Drools-Projekt unterdrücken? Allgemeine Java-Themen 1
D Arbeiten mit einem Bitarray Allgemeine Java-Themen 13
D Union in einem Struct in JNA Allgemeine Java-Themen 5
N Apache POI/ neue Reihe in Excel mit einem Button Allgemeine Java-Themen 2
E Datentypen Wie kann ich die Längen der unterschiedlichen Ebenen aus einem Objekt lesen von dem ich weiß, dass es ein mehrdimensionaler Array ist? Allgemeine Java-Themen 3
R Zoom In einem grid Allgemeine Java-Themen 0
M java.io.EOFException bei einem DataoutputStream ?! Allgemeine Java-Themen 2
D Kgv aller Paare aus einem Array mit n integer berechnen Allgemeine Java-Themen 5
D Verkauf von einem Programm welches ich in Java geschrieben habe Allgemeine Java-Themen 4
M Fahrtsimulation von einem Zug Allgemeine Java-Themen 0
A 2D-Grafik Einfachster Ansatz, um sich wiederholende Figur in einem 2D-Image zu erkennen Allgemeine Java-Themen 1
P einen public <Optinal String> in einer anderen Klasse mit einem Int vergleichen Allgemeine Java-Themen 2
Drachenbauer Wie kann ich das Wort "concrete" in einem String durch ein anderes Wort ersetzen lassen? Allgemeine Java-Themen 5
J Suchen von einer Scannereingabe in einem HashSet Allgemeine Java-Themen 1
L Input/Output Kassenzettel lesen aus einem Bild Allgemeine Java-Themen 2
G JTextField Inhalt in einem Long einfügen Allgemeine Java-Themen 2
M Bei String.format ein Komma statt einem Punkt ausgeben lassen Allgemeine Java-Themen 1
K Bild in einem anderen Bild suchen Allgemeine Java-Themen 12
B Problem zu einem Java Projekt Allgemeine Java-Themen 6
ralfb1105 Starten Java App(s) (.jar) aus einem Java Programm Allgemeine Java-Themen 18
B Suche nach einem Testprogramm für meine BA Allgemeine Java-Themen 0
B Maven Zugriff auf files aus einem kompilierten jar Allgemeine Java-Themen 15
D Warum kann ich eine (deflaut) Klasse aus einer Libary in einem anderen Projekt benutzen? Allgemeine Java-Themen 3
R Farbe zu einem Eckpunkt generieren Allgemeine Java-Themen 0
C Logfile upload zu einem externen filezilla sftp server Allgemeine Java-Themen 6
X Punkte in einem Feld bestimmen Allgemeine Java-Themen 22
H Laden einer (Resourcendatei) aus einem Jar-File Allgemeine Java-Themen 17
J In einem Set doppelte Elemente erzeugen Allgemeine Java-Themen 4
D HTTP Aufruf einer Methode aus einem Servlet heraus Allgemeine Java-Themen 0
S Kann man mit Java auf einem lokalen PC/Mac Benutzergruppen auslesen und Rechte ändern? Allgemeine Java-Themen 11
S Algorithmus welcher True-Werte in einem Array findet und auswertet. Allgemeine Java-Themen 5
R Index in einem Array löschen Allgemeine Java-Themen 10
R Index in einem Array löschen Allgemeine Java-Themen 2
4 Swing Durch klicken auf Button Labels einem Panel hinzufügen Allgemeine Java-Themen 4
The Pi Wie oft wird ein Buchstabe in einem Wort wiederholt? Allgemeine Java-Themen 16
D Kopieren von Dateien aus einem Ordner in einen anderen Allgemeine Java-Themen 6
K Classpath Alle Classen aus einem Package lesen Allgemeine Java-Themen 7
K Auf einer Website nach einem String suchen Allgemeine Java-Themen 5
P Zwei Applikationen mit einem Job Allgemeine Java-Themen 0

Ähnliche Java Themen

Neue Themen


Oben