Socket Bilder übertragen

stulleman

Bekanntes Mitglied
Hallo zusammen!
Ich arbeite gerade an einem kleinen Projekt in dem der Server dem Client ständig screenshots sendet und der Client diese auf einem JPanel darstellt.
Nun stehe ich vor einem Problem, da mein Programm keine Exceptions mehr wirft, es aber trotzdem nicht funktioniert.

Server/Host :

Java:
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.imageio.ImageIO;


public class Server {

	private ServerSocket serverSocket;
	private Socket clientSocket;
	private DataOutputStream dout;
	private Robot robot;
	
	private int screenWidth, screenHeight;
	
	public Server() {
		startServer();
		waitForClient();
		sendScreenshots();
	}

	/**
	 * Starts the server on port 6493
	 */
	private void startServer() {
		try {
			serverSocket = new ServerSocket(6493);
		} catch(IOException e) {
			e.printStackTrace();
		}
		
		System.out.println("Server started...");
	}
	
	/**
	 * Waits for a client to connect
	 */
	private void waitForClient() {
		try {
			clientSocket = serverSocket.accept();
		} catch(IOException e) {
			e.printStackTrace();
		}
		
		try {
			dout = new DataOutputStream(clientSocket.getOutputStream());
		} catch(IOException e) {
			e.printStackTrace();
		}
		
		System.out.println("Accepted client!");
	}
	
	/**
	 * Sends a png screenshot to the connected Client
	 */
	private void sendScreenshots() {
		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		
		screenWidth = dim.width;
		screenHeight = dim.height;
		
		Rectangle screen = new Rectangle(screenWidth,screenHeight);
		
		BufferedImage screenshot;
		
		try {
			robot = new Robot();
		} catch (AWTException e) {
			e.printStackTrace();
		}
		
		while(true) {
			screenshot = robot.createScreenCapture(screen);
			
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
		    try {
				ImageIO.write(screenshot, "png", baos);
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		    byte[] screenBytes = baos.toByteArray();
		    
		    try {
				dout.writeInt(screenBytes.length);
				dout.write(screenBytes);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new Server();
	}
}

Ich denke bis hier hin ist alles richtig oder?
Und hier müsste irgendwo der Fehler liegen:

Java:
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.imageio.ImageIO;

public class Client {

	private Socket socket;
	private DataInputStream din;
	private BufferedImage screenshot;
	
	public BufferedImage getScreenshot() {
		return screenshot;
	}

	public void connectToServer(String ip, int port) {
		try {
			socket = new Socket(ip,port);
			
			din = new DataInputStream(socket.getInputStream());
			
		} catch(UnknownHostException e) {
			e.printStackTrace();
		} catch(IOException e) {
			e.printStackTrace();
		}	
	}
	
	public void getScreenshots() {
		int length;
		byte[] buffer;
		
		while(true) {
			try {
				length = din.readInt();
				
				buffer = new byte[length];
				
				for(int i = 0; i < length; i++) {
					buffer[i] = din.readByte();
				}
				
				ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
				
			    try {
					screenshot = ImageIO.read(bais);
				} catch (IOException e) {
					e.printStackTrace();
				}
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

Frame:

Java:
import javax.swing.JFrame;

public class ClientGUI extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = -3320531674461503451L;

	private ClientGUIPanel panel;
	
	public ClientGUI() {
		initUI();
	}
	
	private void initUI() {
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setTitle("Remote screenshot");
		setSize(600,600);
		
		panel = new ClientGUIPanel();
		add(panel);
		
		setVisible(true);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new ClientGUI();
	}
}

Panel:

Java:
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;

public class ClientGUIPanel extends JPanel 
implements Runnable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7866627091470809232L;
	
	private Client client;
	private BufferedImage screenshot;

	public ClientGUIPanel() {
		client = new Client();
		client.connectToServer("localhost", 6493);
		client.getScreenshots();
		
		Thread thread = new Thread(this);
		thread.start();
	}
	
	@Override
	public void paintComponent(Graphics g) {
		g.drawImage(screenshot, 0, 0, null);
	}

	@Override
	public void run() {
		while(true) {
			screenshot = client.getScreenshot();
			
			repaint();
			
			try {
				Thread.sleep(10);
			} catch(InterruptedException e) {
				
			}
		}
	}
}

Ich denke es wäre zu viel verlangt wenn sich jemand durch den ganzen Code arbeiten soll, aber vielleicht erkennt einer die Struktur dahinter und erkennt darin schon einen Fehler ;)

Danke schon mal!
Max
 

stulleman

Bekanntes Mitglied
Entschuldigung! Ich habe mein Problem selber gelöst!
Das Problem war in der Client Klasse, die getScreenshot() Methode war überflüssig und das Programm ist in der while Schleife hängen geblieben!

Das ist die neue Client Klasse, falls es jemand interessiert ;)

Java:
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.imageio.ImageIO;

public class Client {

	private Socket socket;
	private DataInputStream din;
	private BufferedImage screenshot;

	public void connectToServer(String ip, int port) {
		try {
			socket = new Socket(ip,port);
			
			din = new DataInputStream(socket.getInputStream());
			
		} catch(UnknownHostException e) {
			e.printStackTrace();
		} catch(IOException e) {
			e.printStackTrace();
		}	
	}
	
	public BufferedImage getScreenshot() {
		int length;
		byte[] buffer;
		
		try {
			length = din.readInt();
			
			buffer = new byte[length];
			
			for(int i = 0; i < length; i++) {
				buffer[i] = (byte) din.read();
			}
			
			ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
			
		    try {
				screenshot = ImageIO.read(bais);
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return screenshot;
	}
}
 

stulleman

Bekanntes Mitglied
Eine letzte Frage bleibt noch!
Und zwar stopfe ich den Stream ja mit vielen Bildern voll, und der Client kommt da ja wahrscheinlich nicht hinterher. Würde es sich lohnen den Server erst ein Bild schicken zu lassen wenn das alte gelesen wurde? Oder gibt es da eine bestimmt Technik?
 

Cola_Colin

Top Contributor
Wäre der limitierende Faktor nicht eher das Netzwerk und nicht die Darstellung des Bildes beim Clienten ?
Einfach nur anzeigen kann man pro Sekunde sicher mehr Bilder als man pro Sekunde Bilder übers Netzwerk schicken kann oder pro Sekunde mit dem Robot Screenshots machen kann.
Eigentlich sollte also eher der Client viel auf den Server warten und nicht andersherum ?
 

stulleman

Bekanntes Mitglied
Ach so, das war mir nicht bewusst ;)
Das heißt nicht der Stream wird voll gepackt, sonder der Client wartet lange auf ein neues Bild?
Na gut dann brauche ich eine schnellere Methode Screenshots zu machen!
 

Kr0e

Gesperrter Benutzer
1. Das löst TCP, dein Protokoll ;) TCP sendet nur die TCP window size. Danach muss erstmal von der GEgenseite bestätigt werden, einer der Gründe warum TCP geringfügig langsamer ist als UDP -> COntextwechsel. Sprich wenn der Client nicht fertig sein sollte (Was aber aus Gründen der langsamen Robotfunktion und dem Netzwerk nicht vorkommen sollte), dann blockiert die send() methode des Servers solange, bis das aktuelle Frame geleert ist. Bei google gibts dazu mehr: TCP window size!


2. Schneller wirst du deine Screenshots mit pure Java nicht hinkriegen. Falls es geht, dann musst du auf jeden Fall auf alternative Bilbiotheken ausweichen. DirectX kann das instant, du kannst direkt den VRAM Puffer nehmen -> natürlich nur unter Windows. Auch die GDI+ Alternativen bei Windows sind zu lahm für solche Faxen. Natürlich brauchst du Alternativen für andere Betriebssystem. Da hab ich aber keinen Plan. Manche Forenmitglieber behaupten, dass läge an der zeit, die Java braucht, um Puffer für die Screenshots zu stellen. Das ist seit langem nicht mehr der ausschlaggebende Faktor, sondern einfach das Fehlen des Zugriffs auf die Grafikkarte. Mit DX kann man innerhalb weniger ms einen kompletten SCreenshot machen (Egal ob Hd oder nicht). Bei Java dauert das selbst bei nicht HD gut und gerne mal 100 - 200 ms, je nach Kapazität.

-> JNI wäre hier ein Stichwort, bedeutet aber etwas mehr Arbeit ;-)

Gruß,

Chris
 

stulleman

Bekanntes Mitglied
Ich habe jetzt schon sehr oft von JNI gehört doch ich lerne erst seid einem Jahr Java in der Schule und will mich nicht direkt übernehmen ;)
Vielleicht ist das ja später eine alternative für mich, wollte ja nur raus finden ob ich überhaupt Bilder übers Netzwerk in Echtzeit schicken kann !
Danke trotzdem ;)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
TheJavaKid Bilder mit nem ObjectStream übertragen Netzwerkprogrammierung 8
M Socket Bilder über das Netzwerk übertragen Netzwerkprogrammierung 4
E Bilder übergeben Netzwerkprogrammierung 16
S Socket Bilder über Socket Senden Netzwerkprogrammierung 0
B Socket Bilder verschicken via Sockets. Heap-Problem. Netzwerkprogrammierung 2
B SocketChannel ByteBuffer Bilder verschicken Netzwerkprogrammierung 17
M Socket Bilder senden Netzwerkprogrammierung 1
S Bilder durch's Netzwerk usw ... Netzwerkprogrammierung 10
R Webservice und Bilder Netzwerkprogrammierung 29
F Bilder aus Internet downloaden Netzwerkprogrammierung 12
G Frage zu Servlets und deren Objekte + Bilder in Servlets anzeigen? Netzwerkprogrammierung 11
Benji0815 Bilder oder PDF downloaden Netzwerkprogrammierung 11
H Bilder mit HttpClient hochladen Netzwerkprogrammierung 3
A html - E-mail - Bilder Netzwerkprogrammierung 4
A [URLConnection] Bilder hochladen - aber anders! Netzwerkprogrammierung 4
Lazybone Bilder über Socket Netzwerkprogrammierung 4
P Bilder: FTP-Upload funktioniert nicht richtig Netzwerkprogrammierung 2
A Bei FTP Übertragung wird Datei nicht komplett übertragen Netzwerkprogrammierung 2
I Socket ObjectOutputStream-Socket: Objekt wird falsch übertragen Netzwerkprogrammierung 2
D Socket Gute Idee?: File als byte[] per ObjectIOStream übertragen Netzwerkprogrammierung 3
A RMI RMI - Thread Objekte übertragen und auf anderer Machine weiterlaufen lassen Netzwerkprogrammierung 0
T Anwendungseinstellungen ohne Datei übertragen? Netzwerkprogrammierung 8
A Socket Socket-Problem - Object wird nicht übertragen Netzwerkprogrammierung 3
S Socket Schlüssel übertragen Netzwerkprogrammierung 2
X Kleine Datenobjekte übertragen Netzwerkprogrammierung 10
M Map über Webservice übertragen Netzwerkprogrammierung 3
M Java to php setAsciiStream übertragen Netzwerkprogrammierung 7
K Frame übertragen Netzwerkprogrammierung 8
J Nach Dateiversand werden keine Nachrichten mehr übertragen Netzwerkprogrammierung 11
H ArrayList via WebService übertragen Netzwerkprogrammierung 3
C Client zu Client Daten übertragen Netzwerkprogrammierung 13
S ActiveMQ, JMS und Datei übertragen Netzwerkprogrammierung 25
L Socket publicKey mittels DatagramPacket übertragen Netzwerkprogrammierung 8
J Datei übertragen ja String + datei übertragen nein Netzwerkprogrammierung 5
P Socket Datei von Client zum Server übertragen --> Weiterleitung an Clients Netzwerkprogrammierung 16
Q Problem bei Vergleichen von Strings übertragen über eine Socketverbindung Netzwerkprogrammierung 3
L Audiodateien per Socket übertragen? Netzwerkprogrammierung 2
N Per POST -Methode Daten an den Web-Server übertragen. Netzwerkprogrammierung 9
F Stream wird als Char übertragen. Char -> in String umwand Netzwerkprogrammierung 5
W Objekt über Socket übertragen Netzwerkprogrammierung 14
M Daten übers Netz verschlüsselt übertragen? Wie? Netzwerkprogrammierung 18
S über rmi datei übertragen? Netzwerkprogrammierung 2
G.I.Joe Datei per POST übertragen Netzwerkprogrammierung 2
M dateien übertragen, probleme mit versch. Strömen? Netzwerkprogrammierung 4
S zip-files über sockets übertragen Netzwerkprogrammierung 11
T Rechenserver: Double übertragen Netzwerkprogrammierung 2
S Unix Datei vom Server nach Windows übertragen Netzwerkprogrammierung 8
E Dynamisches übertragen von Stubs Netzwerkprogrammierung 2

Ähnliche Java Themen


Oben