Versand von Nachrichten via Socket (Delay)

mavinatic

Bekanntes Mitglied
Hallo Community,

ich habe mir nen kleinen HTTP-Server gebaut, bzw. bin ich dabei. Nun sende ich von einem Client eine Anfrage und mache ein Thread.sleep(5000); und sende danach nochmal eine Anfrage. Jedoch werden diese beiden Anfragen gleichzeitig versendet, anstatt mit 5 Sekunden pause zwischen beiden anfragen 🙁

Warum?

Client:
Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import org.game.gui.MainFrame;
import org.game.gui.MainPanel;


public class Main {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
//		MainFrame frame = new MainFrame();
//		
//		MainPanel panel = new MainPanel();
//		
//		frame.add(panel);
//		
//		frame.setVisible(true);
		Socket socket = new Socket("127.0.0.1",1234);
		PrintWriter writer = new PrintWriter(socket.getOutputStream());
		BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		
		writer.print("POST /createGame?name=XYZ&maxPlayers=15 HTTP/1.1");
		writer.flush();
		Thread.sleep(5000);
		writer.print("POST /addNewPlayer?playerName=spielerx&playerPositionX=5&playerPositionY=5&game=XYZ HTTP/1.1");

		writer.close();
		reader.close();
		socket.close();
	}

}

Consolenausgabe des Servers:
Java:
Welcome to my HTTP Server at Port: 1234
POST /createGame?name=XYZ&maxPlayers=15 HTTP/1.1POST /addNewPlayer?playerName=George&playerPositionX=5&playerPositionY=5&game=XYZ HTTP/1.1
 
erkennst du den nicht vorhandenen Zeitversatz noch an anderen Dingen außer der Konsolenausgabe, die nichtmal Zeitangaben enthält?
was ist denn der Empfänger, ein Java-Programm von dir oder irgendwas an Standard-Webserver?
funktionieren die Requests abgesehen von dem Log?

dass beides in einer Zeile steht legt nahe, einen Zeilenumbruch \n am Ende des ersten Posts zu senden
(edit: bzw. println statt print), ausprobiert?
oder wenigstens ein Leerzeichen
 
Zuletzt bearbeitet von einem Moderator:
nur so am Rande, wenn du einen Query String hast, dann solltest du GET verwenden. Bei POST wartet die Gegenstelle auf weitere Daten.
 
Ich bin mir bewusst, dass kein konformer HTTP Server ist! Und das mit dem POST weiß ich auch, es ist ein vorstadium zum Testen ;-)

Ich erkenne den Zeitversatz darin, dass ich das programm starte und in die server konsole gucke....jeder request wird ausgegeben, aber dieser request wird immer zusammen ausgegeben!
 
es ist nicht so gut, eine Antwort zu schreiben ohne auf alle Punkt einzugehen oder zumindest auf weitere Antworten zu vertrösten

in Ermangelung anderer Gedanken und grenzenlosen Vertrauen in meine Lösung daher reine Wiederholungsantwort:
hast du das zum Zeilenumbruch bedacht/ ausprobiert?
wie sieht überhaupt der Code des Servers in etwa aus, wie wird dort aus dem Socket gelesen?
 
Dort wird der Code entgegen genommen:

Java:
String currentLine = reader.readLine();
	System.out.println(currentLine);
	processCommand(currentLine);

Hier wird er verarbeitet:

Java:
String[] temp = cmd.split(" ");
		
		String tempMethod = temp[0];
		String tempRequest = temp[1];
		String tempProtocol = temp[2];
		
		if(tempMethod.equals("GET"))
		{
			if(tempRequest.contains(HTTPRequests.STATUS_REQUEST))
			{
				writer.write(server.generateStatus());
				writer.flush();
			}
			if(tempRequest.contains(HTTPRequests.COMMON_REQUEST))
			{
				/*
				 * Common Request
				 */
				writer.write("<html><head><title></title></head><body>COMMON_REQUEST</body></html>");
				writer.flush();
			}

Ich hatte die Frage mit dem Zeilenumbruch irgendwie überlesen: Ja ich habe print, println und write ausprobiert, jeweils mit einem flush() dazwischen.
 
also readLine() spricht klar für Zeilenumbruch, bist du dir sicher mit deinen Test?
hast du auch eine Schleife, es sind ja mehrere Zeilen einzulesen?

hier ein vollständiges Programm mit klaren Ergebnis,
erst die 5 sec Verzögerung, dann zweiter Client mit erster Nachricht sofort da:
Java:
public class Test
{

    public static void main(String... args)
        throws Exception
    {
        Runnable r = new Runnable()
            {
                public void run()
                {
                    try
                    {
                        ServerSocket se = new ServerSocket(1234);
                        while (true)
                        {
                            Socket s = se.accept();
                            System.out.println(System.currentTimeMillis() + ", new Client");
                            BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
                            String line = null;
                            while ((line = reader.readLine()) != null)
                            {
                                System.out.println(System.currentTimeMillis() + ", " + line);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        throw new RuntimeException(e);
                    }
                }

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


        Socket socket = new Socket("127.0.0.1", 1234);
        PrintWriter writer = new PrintWriter(socket.getOutputStream());
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        writer.print("POST /createGame?name=XYZ&maxPlayers=15 HTTP/1.1");
        writer.flush();
        Thread.sleep(5000);
        writer.print("POST /addNewPlayer?playerName=spielerx&playerPositionX=5&playerPositionY=5&game=XYZ HTTP/1.1");

        writer.close();
        reader.close();
        socket.close();


        socket = new Socket("127.0.0.1", 1234);
        writer = new PrintWriter(socket.getOutputStream());
        reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        writer.println("POST /createGame?name=XYZ&maxPlayers=15 HTTP/1.1");
        writer.flush();
        Thread.sleep(5000);
        writer.println("POST /addNewPlayer?playerName=spielerx&playerPositionX=5&playerPositionY=5&game=XYZ HTTP/1.1");

        writer.close();
        reader.close();
        socket.close();
    }
}
Ausgabe:
Code:
1315226917405, new Client
1315226922409, POST /createGame?name=XYZ&maxPlayers=15 HTTP/1.1POST /addNewPlayer?playerName=spielerx&playerPositionX=5&playerPositionY=5&game=XYZ HTTP/1.1
1315226922409, new Client
1315226922409, POST /createGame?name=XYZ&maxPlayers=15 HTTP/1.1
1315226927414, POST /addNewPlayer?playerName=spielerx&playerPositionX=5&playerPositionY=5&game=XYZ HTTP/1.1
 
Ich habe zu dem Versand noch eine Frage:

Hier habe ich eine schleife, welche immer folgene Zeile an meinen Server schicken soll....aber sie wird nur 1mal verschickt warum?
Java:
public void gameLoop()
	{
		
		Runnable run = new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				while(true)
				{
					try
					{
						writer.println("GET /refreshPositionGet?game=ABC HTTP/1.1");
						writer.flush();
						System.out.println("SEND");
						Thread.sleep(500);
					} catch(Exception e)
					{
						e.printStackTrace();
					}
				}
			}
		};
		run.run();
	}

Ich bekomme beim Server 1x diese Nachricht angezeigt, obwohls eigentlich jedes 500ms geschickt werden müsste?! Warum ist das so?
 
Auf die Frage habe ich - mangels Informationen keine Antwort.ABER:
Java:
Runnable run = new Runnable() {
...
run.run();
Du weisst schon wie man mit Threads arbeitet und für was Runnables genutzt werden?
Die run() eines Runnables direkt aufzurufen ist wohl völliger Quatsch.
Ein Runnable Objekt übergibt man einem Thread und ruft dessen start() auf.
Java:
new Thread(run).start();
 
hihi, tut mir leid war unter Zeitdruck, deswegen diese Programmierweise ;-)
Heißt: Dadurch wurde das Problem gelöst? Ich vermute nein.
Ich bekomme beim Server 1x diese Nachricht angezeigt, obwohls eigentlich jedes 500ms geschickt werden müsste?! Warum ist das so?
Am Senden sollte es nicht liegen. Vermutlich wird auch auf der Client Konsole "SEND" mehrfach ausgegeben.
Daher liegt die Vermutung nahe, dass es am Einlesen auf dem Server liegt...
 
ich habe ja ein Programm mit Server gepostet, wenn du dort gleichzeitig diesen Client laufen läßt,
dürfte auch mehrfach empfangen werden, stimmts?

das zeigt wie unsinnig die Frage strenggenommen ist, nicht böse gemeint aber mitdenken würde helfen,
entweder geht es mit meinem Programm nicht, dann speziell drauf hinweisen,
oder es geht, so dass offensichtlich der Client-Code ausreichend gut ist und es wie gesagt wurde an deinem unbekannten Server liegen könnte
 
Soweit kann ich sagen das du richtig liegst mit deiner Aussage, dass es eigentlich gehen müsste, jedoch auch mit copy paste von deinem quellcode funktionierts nicht.

Schleife mit versand von Daten an den Server:
Java:
public void gameLoop()
	{
		
		Runnable run = new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				while(true)
				{
					try
					{
						writer.println("GET /refreshPositionGet?game=ABC HTTP/1.1");
						System.out.println("SEND");
						Thread.sleep(500);
					} catch(Exception e)
					{
						e.printStackTrace();
					}
				}
			}
		};
		new Thread(run).start();
	}

Serverseite - Entgegennahme der Daten und verarbeitung durch "processCommand(...);"
Java:
@Override
	public synchronized void run() 
	{
		try
		{
			String currentLine = reader.readLine();
			System.out.println(currentLine);
			processCommand(currentLine);
			
			this.reader.close();
			this.writer.close();
		} catch(Exception e)
		{
			e.printStackTrace();
		}		
	}
 
nicht mit Nebensächlichkeiten aufhalten, zumindest kommen alle Zeilen an, oder 😉
dass der Code nicht perfekt ist ist klar
(edit: wobei ein Ende der Verbindung vom Client aus durchaus reichen könnte, alles intensiv zu testen oder nachzulesen oder zur Sicherheit auch close() beim Server)

zu deinem:
du willst mehrere Zeilen empfangen, hast eine Schleife beim Sender, aber keine beim Empfänger?!
 
Zuletzt bearbeitet von einem Moderator:
Sorry, auf Clientseite wird tatsächlich keine Exception geworfen. Dein Fehler liegt im Schließen des Readers auf Serverseite, damit ist die Verbindung zwischen Server und Client tot.

Hier mal zur Demo wie Du es gerade umgesetzt hast:
Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;


public class Demo {

	public Demo() {
		new Thread(new Runnable() {
			public void run() {
				try {
					ServerSocket server = new ServerSocket(6666);
					Socket socket = server.accept();
					BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
					System.out.println(reader.readLine());
					reader.close(); // hiermit wird die Verbindung gekappt
					System.out.println(socket.getInputStream());
				} catch (IOException e) {
					System.out.println("Server: " + e.getMessage());
					e.printStackTrace();
				}
			}
		}).start();
		try {
			Socket socket = new Socket("localhost", 6666);
			PrintWriter writer = new PrintWriter(socket.getOutputStream());
			System.out.println("Client: sende Nachricht 1");
			writer.println("Heyho Nummer 1!");
			writer.flush();
			System.out.println("Client: sende Nachricht 2");
			writer.println("Heyho Nummer 2!");
			writer.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}	

	public static void main(String[] s) {
		new Demo();
	}
}
Und dann schau Dir mal SlaterB's Server im Vergleich dazu an.
 
Ich habs nun geschnallt! :-D

Server:
Java:
@Override
	public synchronized void run() 
	{
		try
		{
			while(true)
			{
				String currentLine = reader.readLine();
				System.out.println(currentLine);
				processCommand(currentLine);
			}
		} catch(Exception e)
		{
			e.printStackTrace();
		}		
	}
	
	public void disconnect()
	{
		try {
		reader.close();
		writer.close();
		socket.close();
		} catch(Exception e)
		{
			e.printStackTrace();
		}
	}

Meine Frage ist nur noch, wird mein Thread jetzt ewig laufen, weil er auf while true steht? Wie implementiere ich das, dass er so lange läuft wie die Verbindung besteht?

Ich habe einen Befehl erstellt, wo der Client sich vom Server trennen kann:
Java:
public void processCommand(String cmd)
	{
		String[] temp = cmd.split(" ");
		
		String tempMethod = temp[0];
		String tempRequest = temp[1];
//		String tempProtocol = temp[2];
		
		if(tempMethod.equals("GET"))
		{
			if(tempRequest.contains(HTTPRequests.CLOSE_CONNECTION)) {
				disconnect();
			}...
 
> Wie implementiere ich das, dass er so lange läuft wie die Verbindung besteht?
falls du den Server meinst: siehe immer noch meinen Code? 😉

wobei der für aktiven Abbruch von Server nicht ausgelegt ist, im einfachen Fall tatsächlich closen und Exception in der Schleife abfangen
 

Zurück
Oben