# Sendeproblem



## bernd (26. Jul 2004)

Hallo zusammen,
Bin dabei einen Server zu basteln, er soll auf Knopfdruck eine Nachricht versenden.
Macht er aber nicht hat einer ne Idee warum er nicht sendet?


```
public void jbusendenActionPerformed(final ActionEvent evt) {
        chattext = jtfaus.getText();

     //----------------------------------------------------------------
     try
     {
       PrintWriter Out;
        Out=new PrintWriter(
                new DataOutputStream(socket.getOutputStream()),true);
        Out.println("Serverantwort: " + chattext); // sendet
        Out.close();
     }
     catch (Exception e)
        {   System.err.println(e);
        }
        jtfaus.setText("");        // leert das Textfeld
        jtfaus.requestFocus ();   // macht das Textfeld wieder aktiv
  }
```

Das ist der Code der Ereignissprozedur!

Danke schon mal......


----------



## Grizzly (26. Jul 2004)

Vielleicht klappt es mit einem *flush()* ???:L

```
public void jbusendenActionPerformed(final ActionEvent evt) {
        chattext = jtfaus.getText();

     //----------------------------------------------------------------
     try
     {
       PrintWriter Out;
        Out=new PrintWriter(
                new DataOutputStream(socket.getOutputStream()),true);
        Out.println("Serverantwort: " + chattext); // sendet

        // Schreibt die im Puffer befindlichen Zeichen in bzw. ueber die Netzwerkverbindung
        Out.flush();

        Out.close();
     }
     catch (Exception e)
        {   System.err.println(e);
        }
        jtfaus.setText("");        // leert das Textfeld
        jtfaus.requestFocus ();   // macht das Textfeld wieder aktiv
  }
```

BTW: Objekte sowie sollten Variablen im Allgemeinen sollten klein geschrieben werden. Also _out_ statt _Out_.


----------



## Guest (26. Jul 2004)

Funktioniert leider auch nicht, aber trotzdem danke für die Antwort!  :###


----------



## Grizzly (27. Jul 2004)

Warum benutzt Du eigentlich überhaupt einen *DataOutputStream*?

Du kannst doch schreiben:

```
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
```


----------



## Guest (27. Jul 2004)

Ich Poste mal den kompletten Code, vieleicht ist das dann etwas verständlicher!


```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.text.*;
/**
  *
  * Beschreibung.
  *
  * @version 1.0 vom 01.07.2004
  * @author Bernd Löhe
  */

public class meinServer extends JFrame {
  // Anfang Variablen
  static JTextField jtfaus = new JTextField();
  private JButton jbusenden = new JButton();
  static final String newline = System.getProperty("line.separator");
  //------------------------------------------------
   JScrollPane scrollPane = new JScrollPane();
  static final JTextPane jtp1 = new JTextPane();  // static final, das ist wichtig
  static String chattext;
  static Socket socket;
  // Ende Variablen

  public meinServer(final String title) {
    // Frame-Initialisierung
    super("TCP-Server");  // erzeugt den Fensternamen
    addWindowListener(new WindowAdapter() {
      public void windowClosing(final WindowEvent evt) { System.exit(0); } });
    setBounds(30, 30, 700, 450);
    Container cp = getContentPane();
    cp.setLayout(null);

    // Anfang Komponenten
    jtfaus.setText("");
    jtfaus.setBounds(10, 340, 500, 25);
    getContentPane().add(jtfaus);
    jbusenden.setText("senden");
    jbusenden.setBounds(10, 370, 100, 25);
    getContentPane().add(jbusenden);
    jbusenden.addActionListener(new ActionListener() {
      public void actionPerformed(final ActionEvent evt) {
        jbusendenActionPerformed(evt); } });

     jtp1.setBounds(10, 30, 500, 300);
     jtp1.setEnabled(false);
     jtp1.setContentType("TEXT/RTF");
     jtp1.setText("Wilkommen im Chat" + newline);
     getContentPane().add(jtp1);
    
    scrollPane.setViewportView(jtp1);
    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    scrollPane.setBounds(10, 30, 500, 300);
    getContentPane().add(scrollPane, BorderLayout.WEST);

    // Ende Komponenten

    setVisible(true);
  }

  // Anfang Ereignisprozeduren
  public void jbusendenActionPerformed(final ActionEvent evt) {
        chattext = jtfaus.getText();

     //----------------------------------------------------------------
     try
     {
       PrintWriter out;
        out=new PrintWriter(
                new DataOutputStream(socket.getOutputStream()),true);
        out.println("Serverantwort: " + chattext); // sendet
        out.close();
     }
     catch (Exception e)
        {   System.err.println(e);
        }
        jtfaus.setText("");        // leert das Textfeld
        jtfaus.requestFocus ();   // macht das Textfeld wieder aktiv
  }

  // Ende Ereignisprozeduren


public static class echod implements Runnable
{   //PrintWriter Out;
    BufferedReader In;

     public echod (Socket socket)
    {   try // generiere Ein- und Ausgabestreams und einen Thread
        {   //Out=new PrintWriter(
                //new DataOutputStream(socket.getOutputStream()),true);
            In=new BufferedReader(new InputStreamReader(
                new DataInputStream(socket.getInputStream())));
            new Thread(this).start();
                // starte eine Thread (und damit run())
        }
        catch (Exception e)
        {   System.err.println(e);
        }
    }

   public void run ()
        // der Thread, der eine Verbindung verwaltet.

    {   try
        {   while (true) // Echo-Schleife
            {   String strbuff = jtp1.getText();
               String s=In.readLine();
               chattext = jtfaus.getText();
                jtp1.setText(strbuff + s + newline); // Übergibt den Text zum JTextPane
                if (s.equals("QUIT")) break;

                //Out.println(chattext); // sendet
            }
            // Streams immer schließen:
            In.close();
            //Out.close();
        }
        catch (Exception e)
        {   System.out.println(e);
        }
    }


 }
  public static void main(final String[] args){ // Einstieg ins Programm
    new meinServer("meinServer");
     try // generiere wartenden Socket
        {   ServerSocket server=new ServerSocket(6000);
            while (true) // Läßt sich nur durch CNTRL-C abbrechen
            {   Socket socket=server.accept(); // Socket wartet
                new echod(socket); // Verbindung gefunden
            }
        }

        catch (Exception e)
        {   System.err.println(e);
        }

  }

}
```

 :?:


----------



## Guest (27. Jul 2004)

Ach so, wenn ich sende bekomme ich folgende Fehlermeldung:
java.lang.NullPointerException.


----------



## Grizzly (27. Jul 2004)

Hi Bernd,

ich hab mal das Programm etwas aufgedrösselt und etwas umgeschrieben, so dass der Code etwas übersichtlicher wirkt:

```
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Chat Server.
 * @author Bernd Löhe
 * @version [b]1.0[/b], 01.07.2004
 */
public class MeinServer {
	public static void main(final String[] args) {
		JServerFrame frame;
		Echo echo;
		Thread thread;
		
		frame = new JServerFrame();
		frame.setVisible(true);
		try {
			Thread.currentThread().setName("Server");
			ServerSocket server = new ServerSocket(6000);
			while (!Thread.interrupted()) {
				Socket socket = server.accept();
				echo = new Echo(socket, frame);
				thread = new Thread(echo, "Client");
				thread.start();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
```


```
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;

/**
 * Die Oberfläche für den Chat Server.
 * @author Bernd Löhe
 * @version [b]1.0[/b], 01.07.2004
 */
public class JServerFrame extends JFrame {
	private JPanel jContentPane = null;
	private JTextField jEingabeTextField = null;
	private JButton jSendenButton = null;
	private JScrollPane jScrollPane = null;
	private JTextPane jAusgabeTextPane = null;
	
	/**
	 * Erstellt die Oberfläche.
	 */
	public JServerFrame() {
		super("TCP-Server");
		this.initialize();
	}
	
	/**
	 * Initialisiert das Objekt.
	 */
	private void initialize() {
		this.setBounds(30, 30, 700, 450);
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(final WindowEvent evt) {
				System.exit(0);
			}
		});
		this.setContentPane(this.getJContentPane());
	}
	
	private JPanel getJContentPane() {
		if (this.jContentPane == null) {
			this.jContentPane = new JPanel();
			this.jContentPane.setLayout(null);
			this.jContentPane.add(this.getJEingabeTextField());
			this.jContentPane.add(this.getJSendenButton());
			this.jContentPane.add(this.getJScrollPane());
		}
		return this.jContentPane;
	}
	
	private JTextField getJEingabeTextField() {
		if (this.jEingabeTextField == null) {
			this.jEingabeTextField = new JTextField();
			this.jEingabeTextField.setBounds(10, 340, 500, 25);
		}
		return this.jEingabeTextField;
	}
	
	private JButton getJSendenButton() {
		if (this.jSendenButton == null) {
			this.jSendenButton = new JButton("senden");
			this.jSendenButton.setBounds(10, 370, 100, 25);
			this.jSendenButton.addActionListener(new ActionListener() {
				public void actionPerformed(final ActionEvent evt) {
					if (JServerFrame.this.jEingabeTextField != null) {
						// Hier muss das Senden der Nachricht an alle
						// angemeldeten Clients passieren.
						JServerFrame.this.addMessage(JServerFrame.this.jEingabeTextField.getText());
						JServerFrame.this.jEingabeTextField.setText("");
						JServerFrame.this.jEingabeTextField.requestFocus();
					}
				}
			});
		}
		return this.jSendenButton;
	}
	
	private JScrollPane getJScrollPane() {
		if (this.jScrollPane == null) {
			this.jScrollPane = new JScrollPane();
			this.jScrollPane.setViewportView(this.getJAusgabeTextPane());
			this.jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
			this.jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
			this.jScrollPane.setBounds(10, 30, 500, 300);
		}
		return this.jScrollPane;
	}
	
	private JTextPane getJAusgabeTextPane() {
		if (this.jAusgabeTextPane == null) {
			this.jAusgabeTextPane = new JTextPane();
			this.jAusgabeTextPane.setBounds(10, 30, 500, 300);
			this.jAusgabeTextPane.setEnabled(false);
			this.jAusgabeTextPane.setContentType("TEXT/RTF");
			this.jAusgabeTextPane.setText("Willkommen im Chat " + System.getProperty("line.separator"));
		}
		return this.jAusgabeTextPane;
	}
	
	/**
	 * Fügt eine Ausgabe dem Ausgabefeld hinzu.
	 * Diese Methode ist intern synchronisiert.
	 * @param message Die Ausgabe.
	 */
	public void addMessage(final String message) {
		if ((this.jAusgabeTextPane != null) && (message != null)) {
			synchronized (this.jAusgabeTextPane) {
				this.jAusgabeTextPane.setText(this.jAusgabeTextPane.getText()
					+ message + '\n');
			}
		}
	}
}
```


```
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * Der Ausgabe-Thread für einkommende Nachrichten.
 * @author Bernd Löhe
 * @version [b]1.0[/b], 01.07.2004
 */
public class Echo implements Runnable {
	/** Der Socket, der von diesem Thread überwacht werden soll. */
	private Socket socket = null;
	/** Der Reader, der aus der Verbindung liesst. */
	private BufferedReader in = null;
	/** Das Fenster, in dem der empfange Text ausgegeben werden soll. */
	private JServerFrame frame = null;
	
	/**
	 * Erstellt einen Ausgabe-Thread für einkommende Nachrichten.
	 * @param socket Die Socket-Verbindung, über den die Nachrichten kommen.
	 * @param frame Das Server Fenster, über das die Nachricht ausgegeben werden sollen.
	 * @throws IllegalArgumentException Wenn die Socket-Verbindung <code>null</code> ist.
	 * @throws IllegalArgumentException Wenn das Server Fenster <code>null</code> ist.
	 * @throws IOException Wenn ein Ein-/Ausgabe-Fehler auftrat.
	 */
	public Echo (final Socket socket, final JServerFrame frame) throws IOException {
		if (socket == null) {
			throw new IllegalArgumentException("Argument socket is null.");
		}
		this.socket = socket;
		if (frame == null) {
			throw new IllegalArgumentException("Argument frame is null.");
		}
		this.frame = frame;
		this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
	}
		
	public void run () {
		String s = null;
		try {
			while (!Thread.interrupted()) {
				s = in.readLine();
				this.frame.addMessage(s);
				if (s.equals("QUIT")) {
					break;
				}
			}
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
```

Dein Fehler liegt in der Methode _jbusendenActionPerformed_ (habe ich in meinem Code extra weggelassen):

Diese sendet an den letzten Client, der zu Deinem Chat Server eine Verbindung aufgebaut hat, die Nachricht, die der Benutzer in der Oberfläche des Chat Servers eingegeben hat.

Gibt man in der Oberfäche etwas ein, ohne das bisher ein Client eine Verbindung zum Server aufgebaut hat, bekommt man eine NullPointerException, da das Attribut socket noch nicht initialisiert wurde. Hat der letzte Client seine Verbindung schon wieder abgebaut und es wird versucht eine Nachricht zu schicken, dürfte auch eine Exception geworfen werden.

Außerdem denke ich, dass es von Dir gewollt ist, dass alle momentan angemeldeten Clients die Nachicht bekommen sowie später über den Server die Nachrichten austauschen können. Dazu solltest Du die Clients in einer Liste verwalten, auf die auch die Objekte der Klasse _Echo_ Zugriff haben - zumindest indirekt, da dieser synchronisiert werden muss. Dann wird der Client abgemeldet, sobald dieser sich selbst abmeldet. Und die Oberfläche könnte dann an alle Clients in der Liste die Nachricht versenden.


----------



## bernd (28. Jul 2004)

Vielen Dank erst mal, daß du dir solche Mühe gemacht hast.
Deinen Code werde ich mir est mal in aller Ruhe durch den Kopf gehen lassen (bin ja noch Anfänger).
Aber auf den ersten Blick habe ich schon einige interessante Sachen erkennen können die mir bestimmt weiterhelfen werden!

Tausend Dank!!!!!!!

Bernd.


----------

