问题
I'm making a program that sends the clients screen to the server and displays it but it's being extremely slow. It's taking 2-3 seconds for one frame and the upload/download speed is not a problem. Is there anything I'm doing wrong/anything I can change to speed this up?
Server:
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.zip.GZIPInputStream;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Server {
public static void main(String[] args) {
try {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JLabel label = new JLabel();
label.setSize(800, 600);
label.setVisible(true);
JScrollPane scroll = new JScrollPane();
scroll.getViewport().add(label);
panel.add(scroll, BorderLayout.CENTER);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.setSize(800, 600);
frame.setVisible(true);
ServerSocket serverSocket = new ServerSocket(25565);
Socket socket = serverSocket.accept();
GZIPInputStream in = new GZIPInputStream(socket.getInputStream());
BufferedImage image = null;
while(socket.isConnected()) {
image = ImageIO.read(in);
if(image != null) {
label.setIcon(new ImageIcon(image));
label.repaint();
}
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client:
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.io.IOException;
import java.net.Socket;
import java.util.zip.GZIPOutputStream;
import javax.imageio.ImageIO;
public class Client {
public static void main(String[] args) {
try {
Robot robot = new Robot();
Toolkit toolkit = Toolkit.getDefaultToolkit();
Rectangle screen = new Rectangle((int) toolkit.getScreenSize().getWidth(), (int) toolkit.getScreenSize().getHeight());
Socket socket = new Socket("127.0.0.1", 25565);
GZIPOutputStream out = new GZIPOutputStream(socket.getOutputStream());
while(socket.isConnected()) {
ImageIO.write(robot.createScreenCapture(screen), "png", out);
}
out.close();
} catch (AWTException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
回答1:
If you are sending the image as png
the GZIPStream is probable a bad idea. You won't achieve a signicant compression gain as png already has good compression. Depending on the kind of image you can also consider jpeg
to achieve better compression.
But probably the most important is wrapping the output stream with a BufferedOuputStream:
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
You can do the same in the input stream.
回答2:
Your question is contradicting itself.
On the one hand you ask about sending images over a socket. On the other you say "It's taking 2-3 seconds for one frame and the upload/download speed is not a problem."
I suggest that you attempt to profile your application to determine if the bottleneck is in the image capture, the image conversion, the image compression or the socket I/O. Any one of these is a plausible explanation, and guesswork is not a good strategy for identifying the real one.
(And if you already know where the bottleneck is ... don't confuse the issue by including the rest of the steps in your question. For instance, if you already know that the problem is in the image conversion, there's no need to even mention that you are sending the images over the network. But if you don't know this, then don't feed us potentially false information ... like "the upload/download speed is not a problem".)
回答3:
I believe all given answers don't address the problem. I suspect, that the problem is not the network connection, but the ImageIO.read(InputStream) method. This version of the method is just simply insanely slow. The 2-3 seconds would also occur, if you'd try to load it from your local drive as a stream (whereas ImageIO.read(File) performs just fine).
I solved the problem with:
ImageIO.setUseCache(false);
More info here: Byte array to buffered image conversion slow
来源:https://stackoverflow.com/questions/11910607/java-imageio-is-insanely-slow