Java通过套接字发送屏幕截图
我正在开发一个恶作剧程序,但无论如何都有点用处。Java通过套接字发送屏幕截图
目前我试图做的是从客户端获取屏幕截图并在服务器上以JFrame的形式打开屏幕截图。
经过多次尝试,我发现这个未解决的问题How to send images through sockets in java?。
截图通过,但它的切碎,只有约120-135kb完成。在*投票答案中,他在客户端有Thread.sleep()
,然后我关闭了连接,但是我没有尝试它,它被切断了,所以我尝试了它,但是它仍然被切回。我的客户端读取输入数据的类在循环中,每100ms运行一次,所以我认为它的循环速度太快,所以我将其增加到1000ms,并且它仍然被切碎。
我试着用另一种答案的东西就在同线程不同而改变在服务器端的ImageIO.read(new ByteArrayInputStream(imageAr))
到ImageIO.read(new ByteArrayInputStream(imageAr))
,但那个时候没有像走了进来。
这是的,我试过,当我开始原来的方法之一但这根本不起作用! https://javabelazy.blogspot.com/2013/10/sending-screenshot-from-client-to.html。
服务器
package UI;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ViewScreen implements Runnable{
private static Thread t;
@Override
public void run(){
//Screenshot Frame
final JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
t = new Thread(){
public void run(){
try{
int port = 6667;
ServerSocket serverSocket = new ServerSocket(port);
Socket server = serverSocket.accept();
*UI.console.append("[*]Waiting for screenshot on port " + serverSocket.getLocalPort() + "...\n");
DataInputStream in = new DataInputStream(server.getInputStream());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
byte[] sizeAr = new byte[4];
in.read(sizeAr);
int size = ByteBuffer.wrap(sizeAr).asIntBuffer().get();
byte[] imageAr = new byte[size];
in.read(imageAr);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageAr));
ImageIO.write(image, "jpg", new File("screen.jpg"));
server.close();
JLabel label = new JLabel();
label.setIcon(new ImageIcon(image));
frame.getContentPane().add(label);
}catch(IOException e){
e.printStackTrace();
}
}
};
t.start();
frame.setVisible(true);
}
}
服务器这部分代码是一个新的线程,创建一个新的插座和一个新的JFrame显示的屏幕截图。我为什么要这样做?在另一个线程上,我读到只有在套接字关闭时才会发送图像。所以,因为我不想要主要的套接字关闭,否则我失去了连接,我创建了另一个套接字,暂时只会打开屏幕截图。
客户
在服务器端,我补充说,在本地创建的图像只是如果有什么来解决,通过另一条线。
在此先感谢
你假设read()
填充缓冲区。说明中没有这样说。试试这个:
int size = in.readInt();
byte[] imageAr = new byte[size];
in.readFully(imageAr);
readInt()
和readFully()
被保证读取正确的金额,或者在尝试失败。
你也给自己在发送端很难。试试这个:
out.writeInt(size);
out.write(baos.toByteArray());
out.close();
注意flush()
之前close()
是多余的,但你应该关闭外侧输出流套接字,而不是插座周围,让它自动刷新。
事实上,当你在每个图像之后关闭连接时,你可以摆脱大小字和字节数组输入/输出流,并直接从/到插槽执行ImageIO.read/write
。这将节省大量的内存。
我肯定会从这个变化中获得更好的结果。实际上,我在发送端保留'size'作为字节数组,并在读取端保存'size',并且我获得了大部分屏幕,但屏幕的右侧和底部都被捕获。这可能与我使用RDP进行远程编程有关。非常感谢! – xR34P3Rx
考虑到空间和时间成本,我仍然会删除大小字和字节数组流。不要使简单的事情复杂化。 – EJP
hehe ... @EJP,我可以问一下吗? out.writeInt(size); out.write(baos.toByteArray()); out.close(); 对我来说很好。除非我得到规模价值,...我从哪里得到它?图像的int大小或什么? – gumuruh