2016-12-20 9 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()正しい金額を読んで、または試みに失敗することが保証さです。

あなたはまた、送信側であなたに苦労しています。 close()flush()が冗長ですが、あなたはそれ自動フラッシュを取得し、ソケットではなく、ソケットの周りに、最も外側の出力ストリームをクローズする必要があること

out.writeInt(size); 
out.write(baos.toByteArray()); 
out.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

関連する問題