# SocketServer Problem



## Fraiser (31. Jan 2007)

Hallo, ich bräuchte mal eure Hilfe.

Hab eine Oberfläche, durch die mal per Button eine Socketserver Starten und stoppen kann.

Der SocketServer läuft in einem Thread.
Hier ein Auszug.


```
public void run()
   {
      try
      {
         while( !isInterrupted() )
         {
            while( connectionFailed )
            {
               if( sSocket == null )
               {
                  sSocket = new ServerSocket( _Port );
               }
               socket = sSocket.accept();
               is = socket.getInputStream();
               os = socket.getOutputStream();
               connectionFailed = false;
            }

            
              //hier ist noch eine "Endlosschleife, die auch auf bestimmtes Byte wartet
              ...
         }
      }
      catch( IOException e )
      {
         e.printStackTrace();
      }
      catch( Exception e )
      {
         e.printStackTrace();
      }
   }
}
```


Beim StartServer wird das auchgeführt:


```
server = new ServerThread(Integer.valueOf( jtf_serverPort.getText()));
         server.start();
```

Beim StopServer das:

```
server.interrupt();
```

Beim 2. Start des Server, meckert er rum:  Address already in use: JVM_Bind

Versteh schon warum, aber wie kann ich das anders machen?


----------



## sparrow (31. Jan 2007)

Mit Socket.accept() wartest du darauf, dass auf dem Port etwas eingeht.
Ich bin mir im Augenblick nicht sicher ob der Code an dieser Stelle wirklich abbricht wenn ein ein Interrupt augeslöst wird.
Setz mal ein System.out hinter die Schleife, also nach dem while(!isIterrupted), um herauszufinden ob überhaupt aus der Schleife herausgesprungen wird.

Außerdem würde ich die Sockets mit Socket.close() wieder dicht machen wenn sie nicht mehr gebraucht werden.


Gruß
Sparrow


----------



## Fraiser (31. Jan 2007)

sparrow hat gesagt.:
			
		

> ... um herauszufinden ob überhaupt aus der Schleife herausgesprungen wird.



Ja, Der ServerThread wird richtig unterbrochen.




			
				sparrow hat gesagt.:
			
		

> Außerdem würde ich die Sockets mit Socket.close() wieder dicht machen wenn sie nicht mehr gebraucht werden.



Ich denk hier liegt das Problem, denn interrupt() bricht ja den kompletten Thread ab.
Somit kommt ein socket.close() ja zu spät. Gibt ja keine Methode, die nach dem Interrupt aufgerufen wird.   :?


----------



## Gast (31. Jan 2007)

Du kannst am Ende vom catch()-Block noch ein finally { sSocket.close(); } anhängen. Der finally Block wird immer durchlaufen.


----------



## sparrow (31. Jan 2007)

Fraiser hat gesagt.:
			
		

> Gibt ja keine Methode, die nach dem Interrupt aufgerufen wird.   :?



Ähm.. doch.
Wenn Socket.accept() darauf reagiert wird es bestimmt eine Exception werfen, und in dem entsprechenden catch-Block zu dieser Exception kannst du den Socket dann zu machen.

http://java.sun.com/javase/6/docs/api/java/net/ServerSocket.html#accept()


----------



## Fraiser (1. Feb 2007)

Danke für eure Tipps, aber hat leider alles nix geholfen.
Hier mal der komplette Code des ServerThreads.

Also der Server läuft mit jedem Port einmal. Beim zweiten mal bringt er mir wie gesagt den:
java.net.BindException: Address already in use: JVM_Bind

Start des Servers jedesmal mit: 
server = new ServerThread(Integer.valueOf( jtf_serverPort.getText()));
server.start();

stop mit:
server.interrupt();

Das Problem ist, dass er die Bedingung while( !isInterrupted() ) nie erreicht, weil in der noch eine Endlosschleife kommt. Weiss aber nicht, wie ich das anders machen soll.
Ich bräuchte also was, was den Thread komplett beendet und den Port freigibt.

Bin über Hilfe sehr dankbar!


```
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerThread extends Thread implements Runnable
{
   private int _Port;
   private ServerSocket sSocket        = null;
   private Socket socket               = null;
   private InputStream is              = null;
   private boolean connectionFailed    = true;
   
   public ServerThread( int port )
   {
      _Port = port;
   }
   
   public void run()
   {
      try
      {
         while( !isInterrupted() )
         {
            // Verbinungen herstellen
            // bei Fehlern neuer Versuch
            while( connectionFailed )
            {
               if( sSocket == null )
               {
                  sSocket = new ServerSocket( _Port );
                  socket = sSocket.accept();
                  is = socket.getInputStream();
                  connectionFailed = false;
               }
            }
            // die eigentliche Arbeit des Servers

            int c = 0;
        
            // waiting for start-byte
            for( c = is.read(); c != -1 && c != 11; c = is.read() );

            // get data
            int byte1 = is.read();
            int byte2 = 0;
            boolean dataFinished = false;

            while( !dataFinished )
            {
               byte2 = is.read();
               if( byte1 == 28 && byte2 == 13 )
               {
                  break;
               }
               else
               {
                  byte1 = byte2;
               }
            }
            System.out.println( "COMPLETE" );
         }
      }
      catch( IOException e )
      {
         e.printStackTrace();
      }
   }
}
```


Hier auch gleich nochmal die ne TestMain


```
public class Testmain
{

   public static void main( String[] args )
   {
      try
      {
         ServerThread server = new ServerThread(888);
         server.start();
         Thread.sleep( 100 );
         server.interrupt();
//         server= new ServerThread(888);
//         server.start();
      }
      catch( InterruptedException e )
      {
        
         e.printStackTrace();
      }
      
   }
}
```

Mit der Testmain bleibt er bei socket.accept hängen.
is ja ok, denn accept(): The method blocks until a connection is made.

Aber auf Interrupt reagiert der nun nicht.  :?


----------



## Fraiser (1. Feb 2007)

Ich habs nun erstmal über Reflection gemacht, den Socket von außen zu closen. Nicht schön, aber geht erstmal.

Vielleicht hat trotzdem noch jemand eine tolle Idee


----------



## sparrow (1. Feb 2007)

Genau das meinte ich als ich fragte ob die Enlosschleife wirklich beendet wird....
Also wird der Thread eigentlich gar nicht beendet.

Hier mal ein paar Änderungen.
Ist aber nicht getestet.


```
public void run()
   {
      try
      {
         while( !isInterrupted() )
         {
            // Verbinungen herstellen
            // bei Fehlern neuer Versuch
            while( connectionFailed )
            {
               if( sSocket == null )
               {
                  sSocket = new ServerSocket( _Port );
                  socket = sSocket.accept();
                  is = socket.getInputStream();
                  connectionFailed = false;
               }
               // Hier prüfen wir auf Abbruch
               if (isInterrupted()
               {
                  break;
               }
            }
            // die eigentliche Arbeit des Servers

            int c = 0;
       
            // waiting for start-byte
            for( c = is.read(); c != -1 && c != 11; c = is.read() );

            // get data
            int byte1 = is.read();
            int byte2 = 0;
            boolean dataFinished = false;

            while( !dataFinished )
            {
               byte2 = is.read();
               if( byte1 == 28 && byte2 == 13 )
               {
                  break;
               }
               else
               {
                  byte1 = byte2;
               }
               // Vorsichtshalber prüfen wir hier
               // auch noch mal auf Abbruch
               if (isInterrupted())
               {
                  break;
               }
            }
            System.out.println( "COMPLETE" );
         }
         System.out.println("Port-Thread beendet ....");
         if (sSocket != null && (sSocket.isClosed() == false))
         { 
            System.out.print("Der Port ist noch offen, ich schließe ihn...  ");
            sSocket.close();
            System.out.print("done\n");
          }
      }
      catch( IOException e )
      {
         e.printStackTrace();
      }
   }
```


----------



## Fraiser (5. Feb 2007)

ServerSocket.accept() blockiert wirklich, bis eine Anfrage eines Clients eingeht.
Nach dem ein Client eine Anfrage gestellt hat, kann man auch isInterrupted() auswerten.

Ein Server, der durch accept blockiert ist, weil keine Anfrage eines Clients kommt, kann (nur?) beendet werden. wenn man den Socket schließt. Dies führt zu einer Exception "socket closed". Da muss man nun kucken was gemacht werden soll.


----------

