[Java] Przesyłanie XMLi po TCP


(Kamiljano) #1

No więc mam problem z przesyłaniem plików XML po TCP. Oto metoda, której używam, do generowania i wysłania XMLa:

private void sendXmlAnswer(int aid, String sname, String spassword, boolean asuccess) throws Exception

	{

		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();

		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

		// root elements

		Document doc = docBuilder.newDocument();

		Element rootElement = doc.createElement("login");

		doc.appendChild(rootElement);

		Element name = doc.createElement("name");

		name.appendChild(doc.createTextNode(sname));

		Element password = doc.createElement("password");

		password.appendChild(doc.createTextNode(spassword));

		Element id = doc.createElement("id");

		id.appendChild(doc.createTextNode(Integer.toString(aid)));

		Element success = doc.createElement("success");

		success.appendChild(doc.createTextNode(asuccess ? "true" : "false"));

		rootElement.appendChild(success);

		rootElement.appendChild(id);

		rootElement.appendChild(name);

		rootElement.appendChild(password);


		// write the content into xml file

		TransformerFactory transformerFactory = TransformerFactory.newInstance();

		Transformer transformer = transformerFactory.newTransformer();

		DOMSource source = new DOMSource(doc);

		PrintWriter out = parent.getOutputStream();

		StreamResult result = new StreamResult(out);


		transformer.transform(source, result);

		out.flush();

	}

a oto metoda, którą używam do odebrania wiadomości:

private void readAnswer() throws Exception

	{

		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();

		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();

		Document doc = dBuilder.parse(socket.getInputStream());

		doc.getDocumentElement().normalize();


		System.out.println("Root element :" + doc.getDocumentElement().getNodeName());

	}

Problem polega na tym, że owo odczytanie nigdy się nie kończy... otrzymuję tylko SocketTimeoutException i tyle... zgaduję, że przy wysyłaniu powinienem jakoś dać znać, że to już jest koniec wiadomości tak, żeby klient już dalej nie próbował tego czytać... Niemniej jednak nie wiem jak to zrobić...


(nnick) #2

1) Tworzysz pakiet, gdzie np. 1 bajt to typ pakietu [jeżeli zamierzasz to bardziej rozbudować, nie jest to super konieczne], później 4 bajty tworzą int z wielkością pakietu danych, a dalej dajesz już "mięsko" [xml'a]

2) Odbiorca pakietu pobiera najpierw z bufora bajty z nagłówka, konwertujesz 4 bajty odpowiedzialne za rozmiar danych i pobierasz z bufora tą ilość danych [może przyjść w wielu pakietach TCP, zatem powinieneś to zrobić w pętli]

3) W sumie tyle. W kwestii SocketTimeoutException - musisz ustawić w NetworkStreamie (czy jak to się nazywało w Javie) żeby nie było Timeoutu, ewentualnie potraktować to try catch


(Kamiljano) #3

obawiam sie, ze to nie jest odpowiedz na mije pytanie. Odczytanie odbywa sie tutaj automatycznie wiec nie jestem w stanie powiedziec ile znakow juz przeczytalem i ze juz powinienem przestac...


(Kozicki Michal) #4

Na szybko odpowiadając bez sprawdzenia jak to działa.

W metodzie wysyłającej nie korzystałbym bym ze strumienia binarnego, lecz znakowego a sam dokument wcześniej zamieniłbym na tekst - String, wysłał strumieniem znakowym dokument, potem np. 4 razy "\r\n".

W metodzie, gdzie odbywa się odczyt dokumentu odczytywałbym ze strumienia tekstowego, aż do napotkania 4 znaków "\r\n". Następnie po odczytaniu tekstu metodą "parse" (http://docs.oracle.com/javase/7/docs/api/javax/xml/parsers/DocumentBuilder.html#parse(java.lang.String)) zmieniłbym tekst na dokument .

Twój problem może być związany właśnie z używaniem binarnych strumieni lub z nieprawidłowym użyciem gniazd i strumieni. Mianowicie po stronie klienta i serwera należy wywołać metogy "getOutputStrem" oraz "getInputStream". Po więcej informacji odsyłam do dokumentacji http://docs.oracle.com/javase/7/docs/api/index.html, lub pytaj tutaj!! Po to jest forum.