Timberwolf Geschrieben 17. März 2010 Geschrieben 17. März 2010 Moin Moin, ich habe ein kleines Problem mit der entiwcklung einer asynchronen Socketverbindung. Hier erstmal die Grundlage dessen was ich damit vorhabe: Ziel ist es eine Klasse zu schreiben die x Verbindungen zu x verschiendenen Server aufrecht erhält. Bei dem Server handelt es sich um einen Crysis Dedicated Game Server. Dieser verfügt über einen eigenen kleinen HTTP - Server. Das problem an der ganzen sache ist aber das ich mir nicht sicher bin ob die daten die ich im gebe auch beim Server ankommen. Eine Verbindung bekomme ich ohne weiteres nur der rest funktioniert anscheindent nicht. hier seht ihr meine classConnection public classConnection(String serverip, Integer serverport, String pwd){ adr = serverip; p = serverport; pass = pwd; run(); } public void run(){ System.out.println("vor dem eigentlichen run"); SocketChannel sc = null; Charset std = Charset.forName("utf-8"); try { InetSocketAddress isa = new InetSocketAddress(InetAddress.getByName(adr), p); ByteBuffer bb = ByteBuffer.allocate(4096); sc = SocketChannel.open(); Socket client = sc.socket(); client.connect(isa,p); System.out.println("connect: "+ client.getRemoteSocketAddress()); Integer result = sc.write(std.encode("<?xml version=\"1.0\" encoding=\"UTF-8\"?><methodCall><methodName>g_revivetime 10</methodName><params/></methodCall>")); System.out.println("write 1:" +result); if(sc.read(bb) != -1){ System.out.println("if"); bb.flip(); String str = std.decode(bb).toString(); System.out.println(str); } client.close(); System.out.println("nach dem close"); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } Ich würde mich freuen wenn jemand von euch ne idee hat wie man das besser gestallten kann oder ob ich da irgendwo nen Fehler eingebaut habe und ihn aufgrund von Codeblindheit einfach nicht sehe. Danke für die Hilfe und Gruß Timberwolf PS: wenn weitere Infos benötigt werden ist das kein Problem Zitieren
easyDaMan Geschrieben 17. März 2010 Geschrieben 17. März 2010 Was mir als erstes auffällt, ist "public classConnection". Aber das ist wohl mittlerweile behoben, da meckert der Compiler ja. Also, wenn ich dich richtig verstanden habe, dann hast du eine Haupt-Applikation, die die Connection benötigt, um Zeugs aus dem Dediccated Server zu holen. Schau dir mal das Beispiel hier an... ist ein guter Start dafür, um JAva-Netzwerk- Clients zu bauen: KnockKnockClient Naja... und sonst ist bisschen mehr Info nicht schlecht. Ein Listing der aufrufenden Klasse usw. PAX Zitieren
Timberwolf Geschrieben 17. März 2010 Autor Geschrieben 17. März 2010 public classConnection ist der Kontruktor. Was client / Server verbindungen angeht bin ich nicht ganz unbewandert. Das problem was ich habe ist das ich nicht bestätigen kann das der Server den jeweiligen Befehl erhalten und auch ausgeführt hat, da ich nicht verifizieren kann das ich was vom Server zurück bekomme. Es wird bestätigt das ich mit dem Server verbunden bin. mehr aber auch leider nicht. die Klasse wird von einem JInternalFrame aufgerufen das die Daten die hier zurück kommen benötigt um diese darzustellen. Zitieren
flashpixx Geschrieben 17. März 2010 Geschrieben 17. März 2010 Das problem was ich habe ist das ich nicht bestätigen kann das der Server den jeweiligen Befehl erhalten und auch ausgeführt hat, da ich nicht verifizieren kann das ich was vom Server zurück bekomme. Warum nicht? Du bekommst doch was über den Socket zurück oder sehe ich das falsch? Zitieren
Timberwolf Geschrieben 17. März 2010 Autor Geschrieben 17. März 2010 rein theoretisch ja... ich habe das kleine problem das ich den Inputstream vom Socket nicht gelesen komme... nicht weil ich nciht weis wie sindern weil das tool aus mir unerfindlichen gründen einfriert... und das genau in dem augenblick wo ich versuche den InputStream zu lesen. Der Server stellt eine XML/PRC Schnittstelle zur verfügung die ich nicht richtig bedient bekomme. daher vermute ich das ich da einen fehler mache... so sieht der XML - Code aus den ich da rüber schicke.. <?xml version="1.0" encoding="UTF-8"?> <methodCall> <methodName>rcon_connect</methodName> <params><param> <value><string>addr:xxxxx</string></value> </param> <param> <value><string>port:46964</string></value> </param> <param> <value><string>pass:xxxx</string></value> </param> <param> <value><string>connection_distributed 0</string></value> </param> </params> </methodCall> wenn ich heute abend dazu komme dann poste ich hier den Code den Ihr braucht um das einmal komplett nach zu arbeiten... Zitieren
flashpixx Geschrieben 17. März 2010 Geschrieben 17. März 2010 rein theoretisch ja... ich habe das kleine problem das ich den Inputstream vom Socket nicht gelesen komme... nicht weil ich nciht weis wie sindern weil das tool aus mir unerfindlichen gründen einfriert... Ich würde da folgendes probieren: Schreib Dir mal ein kleines Testprogramm, also genau eine Klasse mit "static int void main" und schick mal die Daten an den Dienst und versuche die Antwort zu erhalten. Bei einer asychronen Verbindung würde ich das so machen: Daten rausschicken und dann innerhalb eines Thread prüfen ob Daten da sind, wenn nicht Thread für eine gewisse Zeit schlafen legen. Im Thread läuft halt eine Schleife die den Socket abfragt ob Daten da sind. Wenn Du keine Daten sendest, deaktivierst Du einfach den Thread. Evtl wäre es sinnvoll, wenn Du zu Beginn eine synchrone Verbindung benutzt um erst einmal das generell zum laufen zu bekommen. Zitieren
Timberwolf Geschrieben 17. März 2010 Autor Geschrieben 17. März 2010 Das mit der synchronen verbindung hatte ich auch schon versucht. da lief es aber genauso. Ich werde mir gleich mal das kleine testtool schreiben und schauen was dabei rauskommt. Wenn ich die Daten an den Port 8080 schicke auf dem der Http Server(CryHttp) läuft bekomme ich mit XML/RPC ein BadRequest.... wenn ich es aber mit einem XML - Debugger an den Rcon port schicke gibt es nur nen Url fehler(http://xxxIPxxx) werde dann gleich mal berichten wie es lief.... Zitieren
Timberwolf Geschrieben 17. März 2010 Autor Geschrieben 17. März 2010 hier mal das kleine testtool. System.out.println() gibt mir zweimal 24 Bytes... da hört es dann bei mir jetzt gerade einfach mal auf public class testmain { /** * @param args */ public static void main(String[] args) { String addr = "87.106.32.16"; Integer port = 8080; Integer rconport = 46964; SocketChannel sc = null; Charset std = Charset.forName("utf-8"); try { InetSocketAddress isa = new InetSocketAddress(InetAddress.getByName(addr), 46964); System.out.println(isa); ByteBuffer bb = ByteBuffer.allocate(4096); String msg = "<?xml version=\"1.0\"?>"+ "<methodCall>"+ "<methodName>rcon_command</methodName>"+ "<params><param>"+ "<value><string>sv_status</string></value>"+ "</param></params>"+ "</methodCall>"; sc = SocketChannel.open(); Socket client = sc.socket(); client.connect(isa); System.out.println("connect: "+ client.getRemoteSocketAddress()); DataInputStream is = new DataInputStream(client.getInputStream()); DataOutputStream os = new DataOutputStream(client.getOutputStream()); while(is.readByte() != 0){ System.out.println(is.readByte()); } for (int n=0; n<20; n++){ bb = std.encode(CharBuffer.wrap(msg)); sc.write(bb); if(bb == null){ System.out.println("Buffer ist leer"); } System.out.println(std.decode(bb)); bb.rewind(); } client.close(); System.out.println("nach dem close"); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } das ist alles was ich hab durchlaufen lassen. Wenn Ihr eine bessere Testlösung oder noch ne idee habt wie ich rausbekomme was mir da übergeben wird schiesst einfach los werde selber noch weiter testen und schauen das ich das irgendwie gelöst bekomme.... danke schonmal für eure Hilfe. grüsse Timberwolf Zitieren
flashpixx Geschrieben 17. März 2010 Geschrieben 17. März 2010 Ich hab mal auf die Schnelle nach diesem Tutorial Creating a Non-Blocking Socket | Example Depot die Verbindung herzustellen. Auf Port 46964 kann ich nicht connecten, da ein "Connection refused" kommt. Auf 8080 kann ich connecten (via Telnet), erhalte aber, wenn ich Deine XML Daten versende: HTTP/1.1 501 Not Implemented Server: CryHttp/0.0.1 Content-Type: text/html Content-Length: 56 <HTML><HEAD><TITLE>Not Implemented</TITLE></HEAD></HTML> Wichtig bei den Socketchannels ist, dass Du prüfst, bevor Du die Daten schreibst, ob der Socket bereit ist. Das muss rein, es dauert bei mir ein paar Sekunden, bis die Verbindung steht. Zitieren
Timberwolf Geschrieben 17. März 2010 Autor Geschrieben 17. März 2010 okay das Tut werde ich mir mal gleich reinziehen und das prüfen werde ich auch noch mit rein nehmen... danke das du es geprüft hast... werde jetzt das alles ausprobieren und dann berichten. Danke & Gruß Timberwolf Zitieren
Timberwolf Geschrieben 18. März 2010 Autor Geschrieben 18. März 2010 So... nach dem ich jetzt mehrere Stunden damit zugebracht habe die verschiedenen Beispiele im Tutorial durch zu kauen bin ich trotzdem leider zu keinem brauchbaren ergebnis gekommen. Ich sehe zwar auf dem Server das da was passiert...also das der Server mich annimmt aber nicht das irgendwas zurück kommt. Bin ja mal ganz ehrlich das ich das mit dem auslesen des ByteBuffers nicht so ganz kapiert habe...und ich denke mal das wenn der rückgabe wert des SocketChannels 0 ist hat der Server den entsprechenden befehl nicht ausgeführt bzw. liefert mir einfach nichts zurück. muss mich korrigieren... hab das eben nochmal getestet und nu bekomm ich einen Intwert von 156 zurück.... wie meinst du das mit dem Thread und der while schleife... beides hab ich nicht in meinem testtool ja nu nicht drin grüße Zitieren
easyDaMan Geschrieben 18. März 2010 Geschrieben 18. März 2010 Er meint, dass du am Besten mal ein Runnable implementierst und dann erstellt du in deiner Main-Klasse einen Thread, dem übergibst du dieses Runnable und startest es. Das frägt den Server nach Daten ab und diese werden dann in dein Socket geschrieben. Solange die Daten vom Server ins Socket geschrieben werden, legst du den Thread schlafen bzw. legst ihn in den Thread-Pool. Das kannst du mit einem if in einem try-catch-Block machen: try{ //if (datenVorhanden){ System.out.println ("geiel"); } catch (InterruptedException ie){ Thread.sleep (500); } Nun werden die Daten übertragen und alle halben Sekunden geht dein Thread schnell fragen, ob nun die Daten alle vorhanden sind. Wenn ja, gehz weiter in deinem Programm: Verarbeitung usw. PS: Mir ist, als haben ByteBuffers noch eine flush()-Methode, die man benutzen muss, um den Inhalt einem StreamReader oder so weiterzugeben. Schau mal in der Doku nach... Das könnte auch noch ein Problem darstellen. PAx Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.