import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;

class TCP2 extends Frame{

// Version & Autor
// Vorläufer-Version VersionsDatum 	        = "06.07.2001"; "11.08.2003";
private static final String VersionsDatum 	= "29.09.2004";
private static final String Autor		= "Manfred Sommer";

private static String Titel = "TCP Verbindungs Test  TCP 2";
private static String newLine = "\r\n";

// TCP/IP Felder

   private static String yourIPAdrStr = "127.0.0.1";
   private static int yourPort = 2001;
   private static InetSocketAddress yourSocketAddress;

   private static int myPort = 2002;
   private static InetSocketAddress mySocketAddress;

// Fonts
    private static final Font FontMono           = new Font("Monospaced", Font.PLAIN, 18);
    private static final Font FontSansSerif 	 = new Font("SansSerif", Font.PLAIN, 14);
    private static final Font BigItalicSansSerif = new Font("SansSerif", Font.ITALIC, 16);

     
// Haupt - Fenstergrösse
    private static int XMax =  460;		
    private static int YMax =  390;
	

// Fenster für Meldungen 
    private static TextArea Mdg1 = new TextArea(5,38);
    private static TextArea Mdg2 = new TextArea(5,38);

// Felder, Label und Fenster für Eingaben
    private static Label     EinLabel = new Label("Eingabe Feld", Label.LEFT);
    private static boolean   NeueEingabe = true;
    private static String    EingabeText = "Anfangs-Text";
    private static TextField EingabeFeld = new TextField(EingabeText,38);
       
	
// Beginn Menü 
  	
    private static MenuBar  MainMenuBar = new MenuBar();
    private static Menu     DateiMenu 	= new Menu("Datei");
    private static MenuItem DateiOpen	= new MenuItem("Öffnen...");
    private static Menu     BearbeitenMenu = new Menu("Bearbeiten");
    private static MenuItem TCPVerb  = new MenuItem("Eröffne TCP Verbindung");
    private static MenuItem PortServer  = new MenuItem("Starte Server Socket");

    private static MenuItem LoeMenu  = new MenuItem("Fenster löschen");
    private static MenuItem Beenden	= new MenuItem("Exit");
    private static Menu     HelpMenu 	= new Menu("Hilfe");
    private static MenuItem AboutBox	= new MenuItem("About");
        
// End Menü 

//// Konstruktor.
 
    TCP2 () {
	super(Titel);
			
	// Fonts für Menüs
	setFont(FontMono);
	DateiMenu.setFont(FontSansSerif);
	DateiOpen.setFont(FontSansSerif);
	BearbeitenMenu.setFont(FontSansSerif);
	TCPVerb.setFont(FontSansSerif);
	PortServer.setFont(FontSansSerif);
	LoeMenu.setFont(FontSansSerif);
	Beenden.setFont(FontSansSerif);
	HelpMenu.setFont(FontSansSerif);
	AboutBox.setFont(FontSansSerif);
	// Font für Text Bereich
	setFont(new Font("Monospaced", Font.PLAIN, 18));
	
	setLayout(new FlowLayout(FlowLayout.LEADING));
	
	setMenuBar(MainMenuBar);
		
	MainMenuBar.add(DateiMenu);
	DateiMenu.add(DateiOpen);
	DateiMenu.add(Beenden);
	
	MainMenuBar.add(BearbeitenMenu);
	BearbeitenMenu.add(TCPVerb);
	BearbeitenMenu.add(PortServer);
	BearbeitenMenu.add(LoeMenu);
		
	MainMenuBar.add(HelpMenu);
	HelpMenu.add(AboutBox);
	
	add(EinLabel);
	add(EingabeFeld);
	
        Mdg1.setEditable(false);
        add(Mdg1);
        Mdg2.setEditable(false);
        add(Mdg2);
               
           
        
        DateiOpen.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ doOpenFile();}
	   });
	
	TCPVerb.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ doTCPVerb();}
	    });	
	
	PortServer.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ doStartPortServer();}
	    });
		
	EingabeFeld.addActionListener(new ActionListener(){    
             public void actionPerformed(ActionEvent e) { 
             	NeueEingabe = true;
                EingabeText = EingabeFeld.getText();
                }
             });
	
	LoeMenu.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ doLoe();}
	    });
	
		
	Beenden.addActionListener(new ActionListener(){
	    public void actionPerformed(ActionEvent e){ FensterBeenden(); }
		});
		

	AboutBox.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent e){ showAboutBox(); }
		});
	    
		
	addWindowListener(new WindowAdapter() {    
	        public void windowClosing(WindowEvent e) { FensterBeenden(); }
		});
		    
	setBackground(Color.lightGray); 
	setSize(XMax, YMax);   
	setVisible(true);
        }

  void FensterBeenden() {	
	        
                dispose();
                System.exit(0);
            }
            
  // show about box
	void showAboutBox(){
		final Frame 	f 	= new Frame("About Box");
		final Button 	Ok 	= new Button("Ok");
	
		f.addWindowListener(new WindowAdapter() {
		    public void windowClosing(WindowEvent e) {
				f.dispose();
			}
		});
		    
		Ok.addActionListener(new ActionListener(){
	        public void actionPerformed(ActionEvent e) {
				f.dispose();
			}
		});
		
		f.setFont	(BigItalicSansSerif);
		f.setLayout	(new GridLayout(0, 1));
	
		f.add(new Label(" ", Label.CENTER));
		f.add(new Label(Titel, Label.CENTER));
		f.add(new Label("Datum der letzten Änderung: " + VersionsDatum, Label.CENTER));
		f.add(new Label("Autor: Manfred Sommer", Label.CENTER));
		f.add(new Label(" ", Label.CENTER));
		
		f.add(Ok);
		f.pack(); 
		f.setVisible(true);
	}
	
	

  
    void doOpenFile(){
    Mdg1.append("Dummy für: Datei - öffnen.\n");
    }    

  void doTCPVerb(){
    if (yourSocketAddress != null){
    	Mdg1.append("TCP Verbindung besteht bereits ...\n");
    	return;
    	}	
    Mdg1.append("Socket Adresse für " + yourIPAdrStr + " " + yourPort + " ermitteln...\n");
    yourSocketAddress = new InetSocketAddress(yourIPAdrStr, yourPort);
    if (yourSocketAddress == null){
    	Mdg1.append("Client Socket-Adresse ungültig ...\n");
    	return;
    	}
    Mdg1.append("TCP Verbindung aufbauen...\n");
    ClientVerbindung sv = new ClientVerbindung(yourSocketAddress);
    sv.start();
    }

  void doStartPortServer(){
    if (mySocketAddress != null){
    	Mdg1.append("Server für Port " + myPort + " besteht bereits ...\n");
    	return;
    	}
    Mdg1.append("Server für Port " + myPort + " konstruieren...\n");  
    mySocketAddress = new InetSocketAddress(myPort); 
    if (mySocketAddress == null){
    	Mdg1.append("Server Socket-Adresse ungültig ...\n");
    	return;
    	}
    ServerAccept sa = new ServerAccept(mySocketAddress);
    sa.start();	 
    }
    
  void doLoe(){ Mdg1.setText(""); }  

  public static void main(String args[]) {
    new TCP2();
    }

  class ClientVerbindung extends Thread{
  
   private SocketChannel channelClient;

   ClientVerbindung(InetSocketAddress s){
     
     try { // Client channel verbinden
       channelClient = SocketChannel.open();
       channelClient.configureBlocking(false);
       channelClient.connect(s);
       } 
     catch (IOException e) {
        Mdg2.append("Client Channel verbinden - Fehler " + e +"\n");
        }
     }

  public void run(){
    Charset charset = Charset.forName("ISO-8859-1");
    CharsetDecoder decoder = charset.newDecoder();
    CharsetEncoder encoder = charset.newEncoder();
    // Allocate buffers
    ByteBuffer buffer     = ByteBuffer.allocateDirect(1024);
    CharBuffer charBuffer = CharBuffer.allocate(1024);

    try {// try Read
      if (channelClient.isConnectionPending()) channelClient.finishConnect();
      Mdg1.append("TCP Verbindung steht!" + newLine);	
      while(true){
      	while ((channelClient.read(buffer)) > 0) {	
	       buffer.flip();
	       decoder.decode(buffer, charBuffer, false);
	       charBuffer.flip();
	       Mdg2.append("Von " + yourIPAdrStr + " : " + charBuffer);
	       buffer.clear();
	       charBuffer.clear();
	       }	
          yield();
          try {sleep(100);}catch(InterruptedException ci){}; 
          }  
      }  // end try Read
    catch (IOException e) { Mdg2.append("Lese Fehler von Client Channel" + e + "\n");}
    
    yourSocketAddress = null;
  }  

} // inner class ClientVerbindung
 
 class ServerAccept extends Thread{
   ServerSocket thisServer;  
   
   ServerAccept(InetSocketAddress s){ 
   	try { // Server Socket verbinden
   	    thisServer = new ServerSocket(); 
   	    thisServer.bind(s);
   	    } 
     catch (IOException e) {
        Mdg2.append("Server Socket verbinden - Fehler " + e +"\n");
        }
   	}

  public void run(){
    try { // to serve the Port
       while (true){
          Mdg1.append("Ich lausche ...\n");
          Socket Verbindung = thisServer.accept(); // Warte auf eine Verbindung
          ServerVerbindung sv = new ServerVerbindung(Verbindung);
          Mdg1.append("Server Verbindung startet ...\n");
          sv.start();
          }
       } 
    catch (IOException e) {
       Mdg1.append("Fehler bei Server.accept" + e +"\n");
       }
    } // to serve the Port 
 } // inner class ServerAccept

class ServerVerbindung extends Thread{
  
   Socket Socke;
   PrintWriter SockeOut;
   
   ServerVerbindung(Socket s){
     Socke = s;
     try { // Input/Output Streams verbinden
        SockeOut = new PrintWriter(Socke.getOutputStream(), true);
       } 
     catch (IOException e) {
        Mdg2.append("Input/Output Streams verbinden - Fehler " + e +"\n");
        }
     }

  public void run(){
    while (true){
    	while (! NeueEingabe) {
    	   yield(); // Nix zu tun ?
    	   try {sleep(100);}catch(InterruptedException ci){};
    	   }
    	SockeOut.println(EingabeText); // Übertragen
    	NeueEingabe = false;
    	}
     }  
 } // inner class ServerVerbindung

}// class TCP1/2
	
 