Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
InputStream einer Socketverbindung funktioniert nicht
Ok ich habe es nun hinbekommen. Anstatt von outstream.close() habe ich flush() verwendet. Wußte nicht, dass er bei close auch die Socketverbindung schließt.
Tjoa mich wunderts auch ein wenig, ist für mich aber die einzigst logische Erklärung. Wenn ich es wieder mit close() probiere bekomme ich SocketClosed Exception
Aber wie kann ich denn alle Daten am Besten auslesen.
Ich bekomme am Anfang einen Http-Header, dann folgt ein Zeilenumbruch und dann kommt die eigentliche Nachricht im XML Format.
Ich habs grad mal folgendermaßen probiert:
Code:
BufferedReader br = new BufferedReader(new InputStreamReader(server.getInputStream()));
int ch;
StringBuffer data = new StringBuffer();
while((ch = br.read()) != -1) {
if(ch != '\n'){
data.append((char)ch);
}else{
System.out.println(data.toString());
data = new StringBuffer();
}
}
Dann bekomm ich halt die Zeilen ausgegeben, aber ich schaffe es nicht sie in einen String oder Strinbuffer einzufügen, so dass ich diesen später parsen kann.
public void createXML() throws IOException {
Socket server = new Socket("192.168.0.123", 80);
System.out.println("connected to " + server.getInetAddress());
DataOutputStream outstream = new DataOutputStream(
new BufferedOutputStream(server.getOutputStream()));
String message = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
+ "<SessionLogin>\r\n" + "<user>" + user + "</user>\r\n"
+ "<password>" + password + "</password>\r\n"
+ "</SessionLogin>";
int lengthString = message.length();
String header = "POST / HTTP/1.1\r\n" + "Content-Type: text/xml\r\n"
+ "User-Agent:xy\r\n" + "Host:12345678\r\n"
+ "Content-Length:" + lengthString + "\r\n"
+ "Connection: Keep-Alive\r\n"
+ "Cache-Control: no-cache\r\n\r\n";
String packet = header + message;
System.out.println(packet);
outstream.writeUTF(packet);
outstream.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(server
.getInputStream()));
StringBuffer data = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
data.append(line);
}
br.close();
}
Das ist jetzt quasi mein kompletter Quelltext. Das Problem ist momentan, dass ich nicht alle Daten bekomme. Nach der Leerzeile wird noch eine Zeile ausgespuckt und das war es dann. Außerdem wird das Programm dauerhaft ausgeführt, auch wenn ich die Socketverbindung am ende wieder trenne. Woran können diese beiden Sachen liegen ?
Oder gibt es generell einen besseren Weg das ganze umzusetzen ?
Serverseitig muss ich mir auf jeden Fall alles manuell zusammenbasteln(Header + XML Nachricht), da auf dem Server kein Java Tool läuft.
achso, es geht um einen HTTP-Request. Dann geht das mit der while-Schleife so nicht. Es gibt zwei Möglichkeiten HTTP-Antworten zu empfangen.
1. der Header enthält ein "Content-Length:" Attribut. Dann ist es einfach, man liest einfach entsprechend viele Daten ein.
2. wenn 1. nicht geht, muß man soviel lesen, wie was kommt. Und wenn dann nichts mehr kommt, müsste man noch einen Timeout abwarten, ehe man davon ausgehen kann, daß da nichts mehr kommt. (Echt blöd )
Genau. Ich hatte mir es eigentlich auch vorgenommen, dass ganze über Content Length zu machen.
Wie kann ich aber denn nach diesem Wert parsen ?
Ein anderes Problem ist:
Code:
while ((line = br.readLine()) != null) {
System.out.println(line);
data.append(line);
}
Dies scheint eine Endlosschleife zu sein. Er geht dort nicht mehr raus, obwohl er eigentlich alle Daten liest.
Dies ist die letzte Zeile die er bekommt: "<sessionloginreply>\r\n"
Er versucht aber scheinbar weiterhin Daten einzulesen, bzw. readLine() kann danach ja immer noch nicht = null sein, sonst würde er ja die Schleife verlassen.
Irgend eine Idee woran das liegen könnte =?
Und ich versteh auch nicht warum er überhaupt die Nachricht ließt, da der Header von der Nachricht durch eine Leerzeile getrennt ist. Dann sollte er ja eigentlich dort aufhören.... ?
nein, Leerzeile ist Leerzeile (also "") und nicht null. Du mußt schon selbst erkennen, wann der Header zuende ist (z.B. durch line.length() == 0). In diesem Fall verläßt du die Schleife, kannst den bis hier geladenen Teil (den Header) nach "Content-Length:" parsen (du könntest natürlich auch schon beim lesen des Headers nach dem Attribut ausschau halten). Wenn du den Wert dann hast, liest du weiter vom BufferedInputStream (diesmal nicht mehr mit readLine) bis du den gesamten Content geladen hast.
Das ist ja alles schön und gut, aber es funktioniert nicht wirklich... weil der Server halt auch nicht über Java eine Verbindung aufbaut und ich dort nur eingeschränkte Möglichkeiten habe, wobei ich ausschließlich eine Socketverbindung über Port 80 herstellen kann. Die Nachrichten werden dann generell von beiden Seiten mittels selbst erzeugten Http Posts versendet.
Dies muss ich serverseitig bspw. auf jeden Fall so machen...
Ich wüßte nicht wie ich meinen Code dahingehend ändern könnte, dass es mit HttpClient funktioniert... ?!?
Schau dir das Beispiel aus dem kleinen Tutorial, das ich verlinkt hatte, mal an:
Code:
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.params.HttpMethodParams;
import java.io.*;
public class HttpClientTutorial {
private static String url = "http://www.apache.org/";
public static void main(String[] args) {
// Create an instance of HttpClient.
HttpClient client = new HttpClient();
// Create a method instance.
GetMethod method = new GetMethod(url);
// Provide custom retry handler is necessary
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler(3, false));
try {
// Execute the method.
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: " + method.getStatusLine());
}
// Read the response body.
byte[] responseBody = method.getResponseBody();
// Deal with the response.
// Use caution: ensure correct character encoding and is not binary data
System.out.println(new String(responseBody));
} catch (HttpException e) {
System.err.println("Fatal protocol violation: " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("Fatal transport error: " + e.getMessage());
e.printStackTrace();
} finally {
// Release the connection.
method.releaseConnection();
}
}
}
Die Zeilen 31 und 35 kann man mit nem Blick in die JavaDocs von HttpClient ändern, es steht aber auch im Tutorial:
It is vital that the response body is always read regardless of the status returned by the server. There are three ways to do this:
* Call method.getResponseBody(). This will return a byte array containing the data in the response body.
* Call method.getResponseBodyAsString(). This will return a String containing the response body. Be warned though that the conversion from bytes to a String is done using the default encoding so this method may not be portable across all platforms.
* Call method.getResponseBodyAsStream() and read the entire contents of the stream then call stream.close(). This method is best if it is possible for a lot of data to be received as it can be buffered to a file or processed as it is read. Be sure to always read the entirety of the data and call close on the stream.
For this tutorial we will use getResponseBody() for simplicity.
Ja ich hab mich da vorher auch shcon mit befasst, bin aber zu dem Schluss gekommen, dass ich es so wie ich es nun mache auch ganz gut hinbekomme. Im Moment funktionierts sogar :wink:
Habe grad nur ein Problem mit dem Parsen der XML Nachricht.
Ich parse diese grade mit Stax. Problem ist nur, ich muss ihm dann ja den InputStream übergeben.
Gibt es auch irgendwie eine Möglichkeit einen String nach XML zu parsen ?
br = BufferedReader, mit dem ich bereits vorher den Http Header und die Content-Length ausgelesen habe. Aber wo soll ich nun in diesem Fall die COntent Length angeben ? Bei dieser Variante scheint er nämlich wieder in der EndlosSchleife zu bleiben und versuchen weitere Daten zu lesen, obwohl keine mher vorhanden sind....