[Java] Przesyłanie XMLi po TCP

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ć…

  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

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…

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.