Socket Server-Socket wiederholt starten

alihallo

Neues Mitglied
Guten Tag,

ich arbeite momentan an einem Projekt. Da ich momentan wirklich nicht mehr weiterweiß habe ich mir gedacht vielleicht kann ich bei Euch Hilfe bekommen.

Ich muss im Voraus sagen, dass ich in der Richtung noch nie etwas gemacht habe und ich mir mit Hilfe einiger Tutorials das folgende zusammengebaut habe.

Es geht darum: Sobald ich einen Button drücke, stellt der "Server" sich in Bereitschaft (d.h. er geht in eine Endlosschleife) und lauscht an dem Port 1234. Sobald nun ein anderer PC, ein Client, an diesen Port/IP eine Nachricht schickt, empfängt der Server diese, speichert sie ab. Das funktioniert soweit.
Ich befinde mich nun allerdings immer noch in dem Menü, das sich jetzt neu aufbaut und die eben empfangene Nachricht mit einbindet.
Soweit läuft alles einwandfrei.

Jetzt allerdings soll der Button ein zweites mal gedrückt werden, sodass der Server ein zweites mal in Bereitschaft geht und der nächste, also ein dritter PC wieder eine Nachricht an ihn schicken kann. Also im Prinzip einfach das, was bereits funktioniert, nur eben nocheinmal!

Nun bekomme ich allerdings die Meldung

Java:
java.net.BindException: Address already in use: JVM_Bind

Ich weiß nicht wie ich das Problem lösen kann, bin hier am verzweifeln. Ich bin der Meinung das ich den Server, den Client, einfach alles sauber schließe, sodass ich es doch einfach ein zweites mal öffenen könnte!?

Hier ein paar relevante Auszüge:


Wenn ich den Button drücke wird folgendes ausgelöst:
Java:
		    spielerWartenButton.addSelectionListener(new SelectionAdapter() 
		    {
		        public void widgetSelected(SelectionEvent e )
		        {
		        	try 
		        	{		        		
		        		String[] paraAngekommen = new String[2];
		                        
                                        //Hier die entscheidende Methode aufSpielerWarten()
		        		paraAngekommen = aufSpielerWarten();
		    			
                                        //Der nullte Parameter ist die Nachricht, der erste ist "1337"
		        		if(Integer.parseInt(paraAngekommen[1]) == 1337)
		        		{
			        		ipListe[spielerZaehler] = paraAngekommen[0];
			        		spielerZaehler++;
		        		}
		        		
						
					} catch (IOException e2) 
					{
						e2.printStackTrace();
					}

		        	try 
		        	{
			            neuesSpielMenue(darstellung);
			            	
		    		} catch (IOException e2)
		    		{
		    			System.out.print(e2);
		    		}

		        }


Hier die aufgerufene Methode aufSpielerWarten() die den Server in Bereitschaft versetzt

Java:
public static String[] aufSpielerWarten() throws IOException
	{
		ServerSocket server = new ServerSocket(1234);
		
		while(true)
		{
			String[] uebergabe = new String[5];
			Socket client = server.accept();

		    Scanner     input  = new Scanner( client.getInputStream() );
		    PrintWriter output = new PrintWriter( client.getOutputStream(), true );

			for(int i =0; i<2; i++)
			{
				uebergabe[i] = input.nextLine();
			}
							
			output.write(uebergabe[1]);
			output.flush();
			input.close();
			output.close();
			
			if(Integer.parseInt(uebergabe[1]) == 1337)
			{
				System.out.println("Server: Bestätigung erhalten");
				return uebergabe;
			}
		}
	}

Ich drücke also den Knopf, der Server wartet.
Daraufhin führe ich ein anderes Java Programm (der Client) aus mit folgender Methode:

Java:
public static void main (String[] args)
	{

		try {
			Client client = new Client();
			if (client.eigeneIpSenden("10.1.30.179", 1234))
			{
				System.out.println("Client: Eigene IP gesendet!");
			}
		} catch (IOException e) {

			e.printStackTrace();
		}

Java:
public boolean eigeneIpSenden(String ipAdresse, int offenerPort) throws IOException
	{
		Socket socketIPsenden = new Socket (ipAdresse, offenerPort);
		Scanner     input  = new Scanner( socketIPsenden.getInputStream() );
	    PrintWriter output = new PrintWriter( socketIPsenden.getOutputStream(), true );
		
		output.println(Menue.eigeneIP());
		output.println("1337");
		output.flush();
		
		if(Integer.parseInt(input.nextLine()) == 1337)
		{

			output.flush();
			System.out.println("Client: Bestätigung empfangen!");
			socketIPsenden.close();
			input.close();
			output.close();
			
			return true;
		}
		return false;
	}

Das sind alle relevanten Daten. Wie gesagt, das ganze funktioniert, aber eben nur EINMAL.
Das ist ein riesen Problem für mich, weil ich an dieser Stelle einfach nicht weiterkomme.
Sobald ich es also den Button ein zweites mal klicke bekomme ich folgende Meldung:

Java:
java.net.BindException: Address already in use: JVM_BindException in thread "main" java.lang.NumberFormatException: null
	at java.lang.Integer.parseInt(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at netzwerk.Menue$4.widgetSelected(Menue.java:258)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:234)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4066)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3657)
	at netzwerk.Menue.fensterErzeugen(Menue.java:81)
	at netzwerk.Menue.neuesSpielMenue(Menue.java:378)
	at netzwerk.Menue$4.widgetSelected(Menue.java:277)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:234)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4066)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3657)
	at netzwerk.Menue.fensterErzeugen(Menue.java:81)
	at netzwerk.Menue.neuesSpielMenue(Menue.java:378)
	at netzwerk.Menue$2.widgetSelected(Menue.java:163)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:234)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4066)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3657)
	at netzwerk.Menue.fensterErzeugen(Menue.java:81)
	at netzwerk.Menue.main(Menue.java:392)

Ich hoffe jemand kann mir weiterhelfen, vielen Dank schonmal im Voraus,

Alex
 
Nur weil du den Socket in Java schließt heißt nicht das er sofort wieder verfügbar ist. Das liegt ganz wesentlich daran wie das unterliegende Betriebsystem den Socket im TCP/IP Stack wieder freigibt. Das kann unter Umständen schon mal ein paar Sekunden dauern.

Warum willst du den Socket denn überhaupt schließen? Du kannst doch auch einfach mit mehren Clients auf den gleichen Socket verbinden?

Ich würde mir an deiner Stelle einfach ein Framework wie Netty oder Mina zur Hand nehmen und darauf dann deine Applikation entwickeln.
 
bisher wird der server ja nichtmal mit close() geschlossen, da kann man höchstens hoffen dass der Garbage-Collector aufräumt,
mit server.close() funktioniert es bei mir:

Java:
public class Test
{

    public static void main(String[] args)
        throws Exception
    {
        Runnable r = new Runnable()
            {
                public void run()
                {
                    try
                    {
                        while (true)
                        {
                            aufSpielerWarten();
                        }
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }

                }
            };
        new Thread(r).start();


        Thread.sleep(2000);
        client();
        client();
        client();

    }

    public static void client()
    {
        System.out.println("client");
        try
        {
            Client client = new Client();
            if (client.eigeneIpSenden("localhost", 5234))
            {
                System.out.println("Client: Eigene IP gesendet!");
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }


    public static String[] aufSpielerWarten()
        throws IOException
    {
        ServerSocket server = new ServerSocket(5234);

        while (true)
        {
            String[] uebergabe = new String[5];
            Socket client = server.accept();

            Scanner input = new Scanner(client.getInputStream());
            PrintWriter output = new PrintWriter(client.getOutputStream(), true);

            for (int i = 0; i < 2; i++)
            {
                uebergabe[i] = input.nextLine();
            }

            output.write(uebergabe[1]);
            output.flush();
            input.close();
            output.close();

            if (Integer.parseInt(uebergabe[1]) == 1337)
            {
                System.out.println("Server: Bestätigung erhalten");
                server.close();
                return uebergabe;
            }
        }
    }
}


class Client
{

    public boolean eigeneIpSenden(String ipAdresse, int offenerPort)
        throws IOException
    {
        Socket socketIPsenden = new Socket(ipAdresse, offenerPort);
        Scanner input = new Scanner(socketIPsenden.getInputStream());
        PrintWriter output = new PrintWriter(socketIPsenden.getOutputStream(), true);

        output.println("dummy IP");
        output.println("1337");
        output.flush();

        if (Integer.parseInt(input.nextLine()) == 1337)
        {

            output.flush();
            System.out.println("Client: Bestätigung empfangen!");
            socketIPsenden.close();
            input.close();
            output.close();

            return true;
        }
        return false;
    }
}


besser ist in der Tat den Server dauerhaft offen zu lassen, z.B. statische Variable
 
@fassy: Danke dir, ich schau mir das mit den Frameworks mal an, aber ich glaube für meine niedrigen Zwecke wäre das fast schon übertrieben, aber ich schau mal rein.

@SlaterB: Du kannst dir nicht vorstellen wie dankbar ich dir bin, sitzt hier nun seit 3 stunden an dem Problem und schreib hier alles um und am Schluss war die Lösung zwei Wörter... Vielen vielen Dank, es geht erstmal.

Aber da ihr beide empfohlen habt das ganze anders zu lösen mach ich mich mal direkt ran. Deshalb wärs wahrscheinlich am Besten wenn ihr den Thread noch offen lasst, ich komm bestimmt bald wieder bei so super Hilfe bei Euch 🙂


Vielen Dank, Alex
 

Zurück
Oben