RCON robot - chyba při čtení packetu – Java – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

RCON robot - chyba při čtení packetu – Java – Fórum – Programujte.comRCON robot - chyba při čtení packetu – Java – Fórum – Programujte.com

 
Hledat
Vybavení pro Laser Game
Spuštěn Filmový magazín
Laser Game Brno
Pergoly a střechy Brno

JS
~ Anonymní uživatel
10 příspěvků
2. 11. 2016   #1
-
+1
-
Zajímavé

Zdravim,

snažím se udělat robota, kterej čte pomocí rconu chat ve hře serveru a pokud někdo napíše příkaz, měl by na něho zareagovat.

V podstatě potřebuju každých 5sec zkontrolovat příkaz chat.tail <pocet_radku> (vypíše posledních x řádků z chatu ve formátu JSON) vyfiltrování nových zpráv a podobně mám hotové, ale když si pošlu víc jak asi 8 posledních zpráv, tak mí java hodí chybu, že je stream poškozen:

java.io.IOException: Stream corrupted.
	at rconbot.base.Packet.read(Packet.java:47)
	at rconbot.base.RconClient.read(RconClient.java:56)
	at rconbot.base.RconClient.read(RconClient.java:58)
	at rconbot.Rconbot.readPackets(Rconbot.java:91)
	at rconbot.Rconbot.main(Rconbot.java:46)

Packet.java:

    public void read(InputStream in) throws IOException {
        packetLength = readBigEndianInt(in);
        packetId = readBigEndianInt(in);
        packetType = Type.valueOfServer(readBigEndianInt(in));
        byte[] bodyBytes = new byte[packetLength - 10];
        if (bodyBytes.length != 0) {
            if (in.read(bodyBytes) == -1)
                throw new IOException("Stream corrupted.");
        }
        if (in.read() != 0 || in.read() != 0)
            throw new IOException("Stream corrupted."); // - - - - řádek 47
        body = new String(bodyBytes, Charset.forName("ASCII"));

    }


rconbot.java: (už jen zpracování přijatého stringu)

    public void readPackets() throws IOException {
        while (client.connected()) {
            String ret;
            ret = client.read().getBody();
            readJSON(ret);
            log.add(ret);
        }
    }

Další otázka je:

Program sám o sobě je jedno vlákno (připojení na server, čtení dat ze serveru).

Druhé vlákno mám jen na tehle cyklus posílání tohoto příkazu.

Ted me jde o to, jak LIVE přenášet nějaký proměný mezi těma vláknama?
Příklad:

Ve hře napíšu příkaz !online - ten zjistim
ted v programu potřebuju poslat příkaz "status" na zjištění počet hráčů na serveru
Následně zase potřebuju počkat na odpověd a vrátit jí do stejný třídy, kde byl vykonán požadavek aby se mohl returnout zpět a udělat příkaz /say <pocetonline>

Napadá vás nějaký jednoduchý řešení? udělat další vlákno na tyhle mezipříkazy? díky
 

Nahlásit jako SPAM
IP: 185.99.119.–
gna
~ Anonymní uživatel
1508 příspěvků
7. 11. 2016   #2
-
0
-

Ten InputStream je ze socketu, takže při pokusu číst větší množství dat, to možná nenačte všechno. Takhle by to šlo ošetřit (pokud to nezabere, tak je ten stream skutečně poškozený) : 

public void read(InputStream in) throws IOException {
	packetLength = readBigEndianInt(in);
	packetId = readBigEndianInt(in);
	packetType = Type.valueOfServer(readBigEndianInt(in));
	byte[] bodyBytes = new byte[packetLength - 10];
	// zmena >>>
	int offset = 0, read;
	while (offset < bodyBytes.length) {
		read = in.read(bodyBytes, offset, bodyBytes.length - offset);
		if (read == -1)
			throw new IOException("Stream corrupted.");
		offset += read;
	}
	// <<< zmena
	if (in.read() != 0 || in.read() != 0)
		throw new IOException("Stream corrupted.");
	body = new String(bodyBytes, Charset.forName("ASCII"));
}

public int readBigEndianInt(InputStream in) throws IOException {
	int result = 0, octet;
	for (int i = 0; i < 4; i++) {
		// zmena >>>
		octet = in.read();
		if (octet == -1)
			throw new IOException("Stream corrupted.");			
		// <<< zmena
		result |= octet << i * 8;
	}
	return result;
}
Nahlásit jako SPAM
IP: 213.211.51.–
JS
~ Anonymní uživatel
10 příspěvků
11. 11. 2016   #3
-
0
-

Děkuji, odzkouším to... ještě mě zajímá... Mám v podstatě dvě vlákna, jedno na čtení a druhý na zápis... Jak udělat funkci

String getReq(String cmd) {}

Abych do funkce getReq poslal příkaz, kterej se pošle přes rcon a ta samotná funkce poslala rovnou odpověd?

Nějak sem se v tom zamotal a nedochází mi, jak to logicky udělat..

Každopádně díky

Nahlásit jako SPAM
IP: 93.99.138.–
gna
~ Anonymní uživatel
1508 příspěvků
12. 11. 2016   #4
-
0
-

Myslím, že moc nemá smysl číst a zapisovat v různých vláknech. Spíš bych to viděl na zápis i čtení v jednom vlákně v principu nějak takhle:

while (bezim)
{
	while (JeCoCist())
	{
		Cti();
	}

	if (JeNecoPotrebaZapsat())
	{
		Zapis();
		if (PotrebujuOdpoved())
		{
			CtiOdpoved();
		}
	}
}

A pak už můžeš ta čtená/zapisovaná data podle potřeby přehazovat mezi vlákny.

Nahlásit jako SPAM
IP: 213.211.51.–
JS
~ Anonymní uživatel
10 příspěvků
13. 11. 2016   #5
-
0
-

#4 gna
zkoušel jsem takhle  

public String doCmd(String cmd) throws IOException {
    client.executeCommand(cmd);
    while(client.connected()) {
        if(client.read().getBody() != null) {
           return client.read().getBody(); 
        }
    }
    return "";
}


V podstatě pošlu požadavek na zápis do rconu -> čekám dokud nepřijde odpověd, hned jak přijde ji vrátim returnem.

executecommad se provede, ale bohužel zpětně nic nepřečte.... v podstatě bez returnu

Nahlásit jako SPAM
IP: 185.99.119.–
JS
~ Anonymní uživatel
10 příspěvků
13. 11. 2016   #6
-
0
-

Tak vyreseno:

public String doCmd(String cmd) throws IOException {
    String ret = null;
    log.add("Posilam dotaz o " + cmd);
    client.executeCommand(cmd);
    while(ret == null) {
        ret = client.read().getBody();
        if("".equals(ret)) ret = null;
    }
    return ret;
}
public String r() throws IOException {
    String ret;
    ret = client.read().getBody();
    return ret;
}

Ta podmínka if("".equals(ret)) ret = null;

je kvuli tomu, že to každej druhej read() vrátilo práznej string.

Takhle jak to je, to ale šlape... Jen by mě zajímalo, rpoč to občas pošle prázdnej String?

Nahlásit jako SPAM
IP: 185.99.119.–
gna
~ Anonymní uživatel
1508 příspěvků
13. 11. 2016   #7
-
0
-

Jestli myslíš tu předchozí variantu, tak ten read vždycky čte další data. Takže prvním readem něco načteš, ale pak vracíš data dalšího readu.

Jestli myslíš tu poslední, tak do hloubky do toho nevidím, ale teoreticky může existovat packet, který obsahuje jen typ a žádná další data. Taky se přeskakuje packet, pokud je neznámého typu. Kdyžtak spusť nějaký monitor sítě a podívej se, co ti tam lítá.

Nahlásit jako SPAM
IP: 213.211.51.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 9 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032021 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý