Sharing screen via Java socket programming

不想你离开。 提交于 2020-06-29 03:59:46

问题


I am trying to send the live screen of the client to the server. It's a one-way communication till now. They seem to connect, but somehow the whole data might not be sent. I can't understand where the problem lies. Only a still image is shared in spite of a continuous stream of images. Will I have to use another AnimationTimer in the server-class and how? If not, how can I achieve a live sharing of the screen? My code is as follows:

Image info class shared by both server & client:

package sample;

import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;
import javafx.scene.image.WritableImage;

import javax.imageio.ImageIO;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class imageData implements Serializable {
    private transient Image wi;
    private String msg;

    private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        wi = SwingFXUtils.toFXImage(ImageIO.read(s), null);
    }

    private void writeObject(ObjectOutputStream s) throws IOException {
        s.defaultWriteObject();
        ImageIO.write(SwingFXUtils.fromFXImage(wi, null), "png", s);
    }

    public void setWi(WritableImage wi) { this.wi = wi; }

    public Image getWi() { return wi; }
}


Server main class:

package sample;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.WritableImage;
import javafx.stage.Stage;

import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource("sample.fxml"));
        Parent root = loader.load();
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root));
        primaryStage.show();

        Controller controller = loader.getController();
        controller.setM(this);

        try{
            ServerSocket ss = new ServerSocket(8888);
            Socket s = ss.accept();
            new conn(s, controller);
        }catch(Exception e){
            System.out.println(e);
        }
    }

    public void setIV(WritableImage wi) { }

    public static void main(String[] args) {
        launch(args);
    }
}

Server conn class:

package sample;

import javafx.scene.control.Control;
import javafx.scene.image.WritableImage;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class conn {
    private Socket s;
    private ObjectInputStream is;
    private Main m;
    private Controller controller;

    public conn(Socket s, Controller controller) throws Exception {
        this.s = s;
        ObjectInputStream is = new ObjectInputStream(s.getInputStream());
        this.controller = controller;
        connTh cth = new connTh(s, is, controller);
        cth.start();
    }

    public void setMain(Main m) { this.m = m; }

    public void setController(Controller controller) { this.controller = controller; }

    public class connTh extends Thread{
        Socket s;
        private ObjectInputStream is;
        private Controller controller;

        public connTh(Socket s, ObjectInputStream is, Controller controller) throws Exception{
            this.s = s;
            this.is = is;
            this.controller = controller;
        }

        @Override
        public void run(){
            while(true){
                try{
                    imageData id = (imageData)is.readObject();
                    Image newImage = id.getWi();
                    controller.setIv(newImage);
                    //WritableImage oldImage = (WritableImage) controller.getIv();
                }catch(Exception e){
                    System.out.println(e);
                }
            }
        }
    }
}

Server controller:

package sample;

import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;

import java.awt.*;

public class Controller {
    private Main m;
    private conn c;
    @FXML private ImageView iv;
    @FXML private Label lbl;

    public void setIv(Image wi) { iv.setImage(wi); }

    public Image getIv() { return iv.getImage(); }

    public void setM(Main m) { this.m = m; }

    public void setC(conn c) { this.c = c; }
}

Server fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>


<GridPane alignment="center" hgap="10" vgap="10" xmlns:fx="http://javafx.com/fxml" xmlns="http://javafx.com/javafx" fx:controller="sample.Controller">
   <columnConstraints>
      <ColumnConstraints />
   </columnConstraints>
   <rowConstraints>
      <RowConstraints />
   </rowConstraints>
   <children>
      <AnchorPane prefHeight="500.0" prefWidth="500.0">
         <children>
            <ImageView fx:id="iv" fitHeight="347.0" fitWidth="436.0" layoutX="32.0" layoutY="47.0" pickOnBounds="true" preserveRatio="true" />
            <Label fx:id="lbl" layoutX="189.0" layoutY="7.0" prefHeight="30.0" prefWidth="72.0" text="VIEW" />
            <Separator layoutX="113.0" layoutY="35.0" prefWidth="200.0" />
         </children>
      </AnchorPane>
   </children>
</GridPane>

Client main class:

package sample;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.robot.Robot;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.stage.Screen;
import javafx.stage.Stage;

import javax.imageio.ImageIO;
import javax.swing.text.Position;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");

        ImageView iv = new ImageView();
        iv.setFitWidth(500);
        iv.setFitHeight(400);

        Text t = new Text("Screen Sharing");
        t.setTextAlignment(TextAlignment.CENTER);
        t.setFill(Color.FIREBRICK);
        t.setStyle("-fx-font: 18 arial;");

        Button b = new Button("Exit");
        b.setAlignment(Pos.BASELINE_CENTER);
        b.setOnAction(event -> {
            Platform.exit();
        });

        VBox v = new VBox(10);
        v.getChildren().addAll(t,iv,b);
        primaryStage.setScene(new Scene(v, 500, 500));
        primaryStage.show();

        try{
            Socket s = new Socket("localhost", 8888);
            ObjectOutputStream os = new ObjectOutputStream(s.getOutputStream());
            new network(s, os);
        }catch(Exception e){
            System.out.println(e);
        }
    }


    public static void main(String[] args) {
        launch(args);
    }
}

Client network class:

package sample;

import javafx.animation.AnimationTimer;
import javafx.geometry.Rectangle2D;
import javafx.scene.image.WritableImage;
import javafx.scene.robot.Robot;
import javafx.stage.Screen;

import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;

public class network {
    private Socket s;
    private ObjectOutputStream os;

    public network(Socket s, ObjectOutputStream os){
        this.s = s;
        this.os = os;

        new AnimationTimer() {
            int c = 1;
            final Robot robot = new Robot();
            final Rectangle2D bounds = Screen.getPrimary().getBounds();
            WritableImage i =robot.getScreenCapture(wi,bounds);
            imageData id = new imageData();

            @Override
            public void handle(long now) {
                if(c == 1){
                    try{
                        c++;
                        id.setWi(i);
                        os.writeObject(id);
                        os.reset();
                        
                    }catch(Exception e){
                        System.out.println(e);
                    }
                }
                else{
                    try{
                        WritableImage oldImage = (WritableImage)id.getWi();
                        WritableImage newImage = robot.getScreenCapture(oldImage,bounds);
                        if(oldImage != newImage){
                            id.setWi(newImage);
                            os.writeObject(id);
                            os.reset();
                        }
                    }catch(Exception e){
                        System.out.println(e);
                    }
                }
            }
        }.start();
}

来源:https://stackoverflow.com/questions/62565698/sharing-screen-via-java-socket-programming

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!