java, wolne sockety, libgdx

0

Witajcie,
Napotkałem ogromny problem w mojej aplikacji. Pragnę odwzorowywać moją ruszającą się postać w drugim oknie, poprzez przesył lan tcp. Wszystko działa, jednak działa strasznie wolno

  • pousuwałem wszystkie inicjalizujące się zmienne w pętli while()
  • wszystkie hints, socketHints... przesunąłem nad pętle by chodziło to płynnie.
    Co mogę zrobić by gra chodziła płynnie? a moja postać chodziła a nie teleportowała się.
    Jeżeli potrzeba dołączę całe klasy. Z góry dziękuję, bardzo proszę o pomoc

///CLIENT

	public class ClientThread extends Thread{
		
		public void run(){
			
			hints = new SocketHints();
			hints.connectTimeout = 11000;
			
			while(trwanie)
			{
				socket = Gdx.net.newClientSocket(Protocol.TCP, "localhost", 8784, hints );
					if(!socket.isConnected() )
						System.out.println("NIE JEST");
					//System.out.println("socket null?");
				if(socket!=null)
				{
					try {
						socket.getOutputStream().write(new String("CZESC server").getBytes()); // wiadomosc wysylana
						//byte[] read = new byte[1024];
						socket.getInputStream().read(read); //odebrana od servera
						readString = new String(read).trim();
						XY = readString;
						StringToFloat();
						
					} catch (IOException e) {
						e.printStackTrace();socket.dispose();
					}
				}
				//socket.dispose();	
				if(Gdx.input.isKeyPressed(Keys.ESCAPE))
				{
					 WylaczPentle();
					 System.out.println("Wychodzimy z pentli");
					 Gdx.app.exit();
				}
			}
			socket.dispose();		
		}
	} 

//SERVER

	public class ServerThread extends Thread{
		
		public void run()
		{
			hints = new ServerSocketHints();
			hints.acceptTimeout = 12000;
			socketHints = new SocketHints();
			while(trwanie)
			{
				server = Gdx.net.newServerSocket(Protocol.TCP, "localhost", 8784, hints);	
				socket  = server.accept(socketHints);
				if(socket != null)
				{
					//byte[] read = new byte[1024];
					try {
						socket.getInputStream().read(read);
						socket.getOutputStream().write( (WspolzednaX+"/"+WspolzednaY).getBytes());																			//---
						
					} catch (IOException e) {
						e.printStackTrace();
						server.dispose();
					}
				}
				server.dispose();
				if(Gdx.input.isKeyPressed(Keys.ESCAPE))
				{
					 WylaczPentle();
					 System.out.println("Wychodzimy z pentli");
					 Gdx.app.exit();
				}
			}
			server.dispose();	
		}	
	}
1

Proponowałbym zacząć od wyłączenia algorytmu Nagla(http://download.java.net/jdk7/archive/b123/docs/api/java/net/Socket.html#setTcpNoDelay(boolean))
Druga sprawa TCP nie jest idealnym rozwiązaniem wydajnościowych do synchronizowania obiektów.
3. socket.getInputStream().read(read); -> jeśli nie potrzebujesz jakiś danych to ich nie wysyłaj.
4. Przy przesyłaniu danych najlepiej unikać Stringów.
5. Kontekst Gdx nie powinien być wywoływany w innym nie-synchronizowanym wątku.
6. W pętli while masz co obieg tworzenie i wyłączanie socketa - to jest prawdopodobny powód twoich opóźnień ponieważ ta czynność jest fat:)

0
  1. Nie jestem pewny zastosowania
    public void setTcpNoDelay(boolean on)
    {
    }
    ...
    setTcpNoDelay(false);
    ...
  2. ta linijka wyczekuje wiadomości od servera
  3. Wysyłam tablice bytów. Ruch dedykowany jest w floatach konwertuje do intów -> string -> byte[]
  4. nie rozumiem :( co mam zmienić?
    6) ZGODZĘ SIĘ I JESTEM TEGO W PEŁNI ŚWIADOM, ale nie potrafię tego naprawić. Gdy przesuwam poza whila()
server = Gdx.net.newServerSocket(Protocol.TCP, "localhost", 8784, hints);    
                socket  = server.accept(socketHints); 

**Program się wysypuje, wskazać errory? Jak zatem mam to naprawić? co **
gdzie przesunąć? moim zdanie to własnie największy szkodnik mojego programu.

Pozdrawiam i dziękuję

1
   socket  = server.accept(socketHints);

<- wysypuje się bo client musi być też tylko raz inicjializowany. Jedna akceptacja dla jednego połączenia się clienta z serwerem.

0

Jeżeli tylko raz miałby akceptować zatem tworze sb if z tmp, aby tylko raz mogło się połączyć z portem 6783 oraz by tylko raz socket mógł zaakceptować server

public class ServerThread extends Thread{
		
		public void run()
		{
			setTcpNoDelay(false);
			hints = new ServerSocketHints();
			socketHints = new SocketHints();
			
			int tmp = 1;
			while(trwanie)
			{
				if(tmp == 1) // <----------------------------------------------------------------------------------------------------------------------------------------
				{
					tmp=2;
					server = Gdx.net.newServerSocket(Protocol.TCP, "localhost", 8783, hints);	
					socket  = server.accept(socketHints);
					hints.acceptTimeout = 12000;
				}
					
				if(socket != null)
				{
					//byte[] read = new byte[1024];
					try {
						socket.getInputStream().read(read, 0, read.length);
						socket.getOutputStream().write( (WspolzednaX+"/"+WspolzednaY).getBytes());																			//---
						
					} catch (IOException e) {
						e.printStackTrace();
						server.dispose();
					}
				}
				//server.dispose();
				if(Gdx.input.isKeyPressed(Keys.ESCAPE))
				{
					 WylaczPentle();
					 System.out.println("Wychodzimy z pentli");
					 Gdx.app.exit();
				}
			}
			server.dispose();	
		}	

///Exception Server:

Exception in thread "Thread-1" com.badlogic.gdx.utils.GdxRuntimeException: Error accepting socket.
at com.badlogic.gdx.net.NetJavaServerSocketImpl.accept(NetJavaServerSocketImpl.java:87)
at Sockets.Server$ServerThread.run(Server.java:78)
Caused by: java.net.SocketTimeoutException: Accept timed out
at java.net.DualStackPlainSocketImpl.waitForNewConnection(Native Method)
at java.net.DualStackPlainSocketImpl.socketAccept(Unknown Source)
at java.net.AbstractPlainSocketImpl.accept(Unknown Source)
at java.net.PlainSocketImpl.accept(Unknown Source)
at java.net.ServerSocket.implAccept(Unknown Source)
at java.net.ServerSocket.accept(Unknown Source)
at com.badlogic.gdx.net.NetJavaServerSocketImpl.accept(NetJavaServerSocketImpl.java:85)
... 1 more

//Exception CLIENT:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at Sockets.Client$ClientThread.run(Client.java:91)
wyjścieException in thread "Thread-1" com.badlogic.gdx.utils.GdxRuntimeException: Error making a socket connection to localhost:8783
at com.badlogic.gdx.net.NetJavaSocketImpl.<init>(NetJavaSocketImpl.java:51)
at com.badlogic.gdx.backends.lwjgl.LwjglNet.newClientSocket(LwjglNet.java:61)
at Sockets.Client$ClientThread.run(Client.java:84)
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at com.badlogic.gdx.net.NetJavaSocketImpl.<init>(NetJavaSocketImpl.java:46)
... 2 more

Proszę o naprowadzenie mnie w kodzie, rozumiem logike, klient sie podłancza do servera, w zasadzie wielu klientów by mogło. Server nasłuchuje ich non stop albo jest taki timeOUT.
Dziękuję za pomoc

1

Jesteś pewny że serwer odpala się przed żądaniem połączenia przez klienta? Do testów możesz dać między server.run() a client.run() -> Thread.sleep(500)

0

Hmm dobry pomysł, jednak myślałem że linijka

 hints.acceptTimeout = 12000;

załatwia sprawę, w formie threda a jednak wychodzi na to że jednak wciąż brakuje mi wiedzy.
Zgodnie z pomysłem dałem thredy na 0,5sekundy....

//SERVER

				socketHints = new SocketHints();
				server = Gdx.net.newServerSocket(Protocol.TCP, "localhost", 8783, hints);	
				socket  = server.accept(socketHints);
				   Thread.sleep(500, 0);
				   } catch (Exception e) {
				   System.out.println(e);
				   } 

//CLIENT

public void run(){
			
			hints = new SocketHints();
			hints.connectTimeout = 11000;
			try {
					socket = Gdx.net.newClientSocket(Protocol.TCP, "localhost", 8783, hints );
				   Thread.sleep(500, 0);
				   } catch (Exception e) {
				   System.out.println(e);
				   }
			while(trwanie)
			{ 

....i działa !!!!!!!!
Nie wierzyłem że to poskutkuje, oczywiście pomysł był logiczny, server i client muszą się spotkać i zaprzyjaźnić by cokolwiek porobić razem. DZIĘKUJĘ BARDZO !!! siedziałem nad tym kilka dni, buduję grę na dwóch graczy PvP ( o ile jeszcze gdzieś nie utknę), jesteś Pan Wielki :) ! Dziękuje za czas, cierpliwość i chęci

1

Jak już pobawisz się socketami, to możesz uderzyć w https://github.com/EsotericSoftware/kryonet - swego czasu na tym pisałem bibliotekę do multiplayera. Ogólnie radziłbym nie brać się póki co za multi, tylko skupić na systemie ECS dla libgdx albo ashley(prostszy) albo artemis(szybszy)

1 użytkowników online, w tym zalogowanych: 0, gości: 1