簡體   English   中英

Java通過socket發送截圖

[英]Java send screenshot over socket

我正在制作一個惡作劇程序,但無論如何都有點用處。

我目前正在嘗試做的是從客戶端獲取屏幕截圖並在服務器上打開屏幕截圖作為JFrame。

經過多次嘗試,我發現這個未解決的問題如何通過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來顯示屏幕截圖。 我為什么要這樣做? 在另一個線程上,我讀到圖像只會在套接字關閉時發送。 所以,因為我不希望主套接字關閉或者我失去了連接,我創建了另一個套接字,它將暫時打開以僅流式傳輸屏幕截圖。

客戶

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();
    }
}
}

在服務器端,我添加了另一行,在本地創建圖像只是為了解決任何問題。

提前致謝

你假設read()填充緩沖區。 規范中沒有任何內容表明這一點。 嘗試這個:

int size = in.readInt();
byte[] imageAr = new byte[size];
in.readFully(imageAr);

readInt()readFully() 保證讀取正確的量,或者在該嘗試失敗。

你也在發送端給自己一個艱難的時間。 嘗試這個:

out.writeInt(size);
out.write(baos.toByteArray());
out.close();

請注意, close() flush()之前的flush()是多余的,但是應該關閉套接字周圍的最外面的輸出流,而不是套接字,以使其自動刷新。

事實上,當您在每個圖像之后關閉連接時,您可以擺脫大小字和字節數組輸入/輸出流,並直接從/向套接字執行ImageIO.read/write 它會節省大量內存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM