Socket: Strings mit GZIPOutputStream / GZIPInputStream

yigiter

Mitglied
Hallo zusammen,

wie kann ich String komprimiert via Tcp Socket Senden und Empfangen.

Klasse: Zip
Code:
public class ZipUtils {

	private static final String CHARSET_UTF_8 = "UTF-8";

	/**
	 * Gzip the input string into a byte[].
	 * 
	 * @param input
	 * @return
	 * @throws IOException
	 */
	public static byte[] zipStringToBytes(String input) throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		BufferedOutputStream bufos = new BufferedOutputStream(new GZIPOutputStream(bos));
		bufos.write(input.getBytes());
		bufos.close();
		byte[] retval = bos.toByteArray();
		bos.close();
		return retval;
	}

	/**
	 * Unzip a string out of the given gzipped byte array.
	 * 
	 * @param bytes
	 * @return
	 * @throws IOException
	 */
	public static String unzipStringFromBytes(byte[] bytes) throws IOException {
		ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
		BufferedInputStream bufis = new BufferedInputStream(new GZIPInputStream(bis));
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		byte[] buf = new byte[1024];
		int len;
		while ((len = bufis.read(buf)) > 0) {
			bos.write(buf, 0, len);
		}
		String retval = bos.toString();
		bis.close();
		bufis.close();
		bos.close();
		return retval;
	}
}

Kennt jemand ein Tutorial oder ein lauffähiges Beispiel :)

Vielen Dank
 
Hallo,

schau mal hier:
Java:
package de.tutorials;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class StringCompressionExample {

	final static CountDownLatch latch = new CountDownLatch(1);
final static String msg = "A very long message 111222h34jk324hjk4hdfhhfsjkahjkfhjkh34jkhuiz4897489jhkdjkljadiljda97234073j3lj3klj3lj3io13j290uds90dasjdklsjkljdsklj34907404830324sdjasdklköm·…cm,.mc,.cm lökpüi90429044j4j43jk4hjkhrzhsdiz8ousdojkljdkladjkldjaduew8ou89eu894324hjkdhsjkhdjkasdh78974389334jk4hjkhjkhsd89dz891234h111222h34jk324hjk4hdfhhfsjkahjkfhjkh34jkhuiz4897489jhkdjkljadiljda97234073j3lj3klj3lj3io13j290uds90dasjdklsjkljdsklj34907404830324sdjasdklköm·…cm,.mc,.cm lökpüi90429044j4j43jk4hjkhrzhsdiz8ousdojkljdkladjkldjaduew8ou89eu894324hjkdhsjkhdjkasdh78974389334jk4hjkhjkhsd89dz891234h111222h34jk324hjk4hdfhhfsjkahjkfhjkh34jkhuiz4897489jhkdjkljadiljda97234073j3lj3klj3lj3io13j290uds90dasjdklsjkljdsklj34907404830324sdjasdklköm·…cm,.mc,.cm lökpüi90429044j4j43jk4hjkhrzhsdiz8ousdojkljdkladjkldjaduew8ou89eu894324hjkdhsjkhdjkasdh78974389334jk4hjkhjkhsd89dz891234h111222h34jk324hjk4hdfhhfsjkahjkfhjkh34jkhuiz4897489jhkdjkljadiljda97234073j3lj3klj3lj3io13j290uds90dasjdklsjkljdsklj34907404830324sdjasdklköm·…cm,.mc,.cm lökpüi90429044j4j43jk4hjkhrzhsdiz8ousdojkljdkladjkldjaduew8ou89eu894324hjkdhsjkhdjkasdh78974389334jk4hjkhjkhsd89dz891234h";
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		
		benchmark();
		
		
		ExecutorService executorService = Executors.newFixedThreadPool(2);

		executorService.execute(new Server());
		executorService.execute(new Client());

		executorService.shutdown();

	}

	private static void benchmark() throws UnsupportedEncodingException {
		System.out.println("Raw message bytes (UTF-8): " + msg.getBytes("UTF-8").length);
		byte[] compressedMsgBytes = compress(msg);
		System.out.println("Compressed message bytes:   " + compressedMsgBytes.length);
		String decompressedMessage = decompress(compressedMsgBytes);
		System.out.println(msg.equals(decompressedMessage));
	}

	static class Server implements Runnable {
		public void run() {
			try {
				ServerSocket serverSocket = new ServerSocket(4711);
				latch.countDown();

				Socket socket = serverSocket.accept();

				
				socket.getInputStream().read();
				socket
						.getOutputStream()
						.write(
								compress(msg));
				socket.getOutputStream().flush();
				socket.close();

			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	static class Client implements Runnable {
		public void run() {
			try {
				latch.await();
				Socket socket = new Socket("localhost", 4711);
				socket.getOutputStream().write(1);

				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				byte[] buffer = new byte[1024];
				InputStream in = socket.getInputStream();
				for (int bytesRead; (bytesRead = in.read(buffer)) != -1;) {
					baos.write(buffer, 0, bytesRead);
				}

				System.out.println("Received: "
						+ decompress(baos.toByteArray()));

				socket.close();

			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private static byte[] compress(String s) {
		byte[] result = null;
		try {
			byte[] bytesUTF8 = s.getBytes("UTF-8");

			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			GZIPOutputStream zipOut = new GZIPOutputStream(baos);

			zipOut.write(bytesUTF8);
			zipOut.close();

			result = baos.toByteArray();

		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	private static String decompress(byte[] compressedBytes) {
		String result = null;
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			GZIPInputStream zipIn = new GZIPInputStream(
					new ByteArrayInputStream(compressedBytes));

			byte[] buffer = new byte[1024];
			for (int bytesRead; (bytesRead = zipIn.read(buffer)) != -1;) {
				baos.write(buffer, 0, bytesRead);
			}

			result = new String(baos.toByteArray(), "UTF-8");

		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

}

Ausgabe:
Code:
Raw message bytes (UTF-8): 1144
Compressed message bytes:   250
true
Received: A very long message 111222h34jk324hjk4hdfhhfsjkahjkfhjkh34jkhuiz4897489jhkdjkljadiljda97234073j3lj3klj3lj3io13j290uds90dasjdklsjkljdsklj34907404830324sdjasdklköm·…cm,.mc,.cm lökpüi90429044j4j43jk4hjkhrzhsdiz8ousdojkljdkladjkldjaduew8ou89eu894324hjkdhsjkhdjkasdh78974389334jk4hjkhjkhsd89dz891234h111222h34jk324hjk4hdfhhfsjkahjkfhjkh34jkhuiz4897489jhkdjkljadiljda97234073j3lj3klj3lj3io13j290uds90dasjdklsjkljdsklj34907404830324sdjasdklköm·…cm,.mc,.cm lökpüi90429044j4j43jk4hjkhrzhsdiz8ousdojkljdkladjkldjaduew8ou89eu894324hjkdhsjkhdjkasdh78974389334jk4hjkhjkhsd89dz891234h111222h34jk324hjk4hdfhhfsjkahjkfhjkh34jkhuiz4897489jhkdjkljadiljda97234073j3lj3klj3lj3io13j290uds90dasjdklsjkljdsklj34907404830324sdjasdklköm·…cm,.mc,.cm lökpüi90429044j4j43jk4hjkhrzhsdiz8ousdojkljdkladjkldjaduew8ou89eu894324hjkdhsjkhdjkasdh78974389334jk4hjkhjkhsd89dz891234h111222h34jk324hjk4hdfhhfsjkahjkfhjkh34jkhuiz4897489jhkdjkljadiljda97234073j3lj3klj3lj3io13j290uds90dasjdklsjkljdsklj34907404830324sdjasdklköm·…cm,.mc,.cm lökpüi90429044j4j43jk4hjkhrzhsdiz8ousdojkljdkladjkldjaduew8ou89eu894324hjkdhsjkhdjkasdh78974389334jk4hjkhjkhsd89dz891234h

Gruß Tom
 
Vielen Dank für das Beispiel.. funktioniert ohne Probleme..

Was muss ich machen, damit Client und Server dauerhaft miteinander kommunizieren können!

Vielen Dank im Voraus.
 
Hallo,

mit dauerhaft meinte ich, das der Client sich beim Server anmeldet und ab diesem Zeitpunkt diverse Informationen an den Client versendet werden.

Folgendes habe ich vor:
- Client meldet sich beim Server, versendet seine Kundennummer
- Server merkt sich die Kundennummer und die IP Adresse in der einer Conc.-Map
- ab diesem Zeitpunkt erhält der Client z.B. irgendwelche Aktien-Infos
- Nachrichten sollte gezippt versendet werden!
- Verbindung wird beendet wenn der Client sich abmeldet.

D.h. Ich möchte nicht immer eine neue Verbindung zum Server aufbauen, sondern die bestehende beibehalten. Im o. beipsiel, wird nach versenden einer Nachricht die Verbindung beendet.

Viele Güße
 
Dann lass doch in obigem Beispiel die socket.close weg, bzw. pack sie dahin wo sie Sinn machen, also nach Ende deiner Transaktion.
 
Stimmt, du könntest einfach das close weglassen und kontinuierlich auf Nachrichten vom Server lauschen.
Also z.B.
Code:
InputStream is = socket.getInputStream();
while(is.available()>0) {
  // do something
}

Allerdings gibt es bei dieser Methode das Problem das du dir nie sicher sein kannst das wirklich ein kompletes "Paket" übertragen wurde. Es könnte aufgrund von Netzwerkverzögerungen sein das in der Mitte einer Übertragung der InputStream leer läuft. Z.b. der Server sendet "ABCD". Am Client wird A & B empfangen, danach ist aber is.available()==0. Falls dein weiterer Prozess am Client ebenfalls Stream basiert ist dürfte das kein Problem sein. Falls doch musst du dir entweder ein EOT byte( bzw- sequenz) einfallen lassen oder eine feste Protokolllänge definieren oder wie z.b. bei HTML die Paketlänge mit im Nachrichtenkopf mit senden und auswerten.

Alternativ könntest du aber auch gleich ein paketorientiertes Protokoll wie UDP benutzen http://openbook.galileocomputing.de/javainsel8/javainsel_18_011.htm.

VG,
ck.
 
Zuletzt bearbeitet:
Hallo,

danke für die Antworten.

Ich meine, ich hätte das close() aus dem obigen Beispiel entfernt ==> Daraufhin kamen keine Nachrichten beim Client an.. :-) Ich werde es aber nocheinmal ausprobieren..

Gut bei UDP muss der Client die UDP Ports am Router öffnen! Dies wollte ich vermeiden..

Viele Grüße
 
Zurück