本文目录导读:

我来为您提供一个完整的Java屏幕分享案例,包括服务端(共享屏幕)和客户端(查看屏幕)的实现。
项目结构
screen-share/
├── src/
│ ├── Server.java # 屏幕分享服务端
│ ├── Client.java # 屏幕查看客户端
│ └── ScreenShare.java # 公共接口/工具类
完整实现代码
服务端(共享屏幕)
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
private static final int PORT = 8888;
private static final int FPS = 10; // 每秒传输帧数
private static final int QUALITY = 80; // JPEG压缩质量
private ServerSocket serverSocket;
private volatile boolean running = true;
private Robot robot;
private Rectangle screenRect;
public Server() {
try {
robot = new Robot();
screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
} catch (AWTException e) {
e.printStackTrace();
}
}
public void start() {
try {
serverSocket = new ServerSocket(PORT);
System.out.println("屏幕分享服务已启动,端口: " + PORT);
System.out.println("等待客户端连接...");
ExecutorService pool = Executors.newFixedThreadPool(10);
while (running) {
Socket clientSocket = serverSocket.accept();
System.out.println("客户端已连接: " + clientSocket.getInetAddress());
pool.execute(() -> handleClient(clientSocket));
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleClient(Socket socket) {
try {
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
while (running && !socket.isClosed()) {
long startTime = System.currentTimeMillis();
// 捕获屏幕
BufferedImage screenshot = robot.createScreenCapture(screenRect);
// 压缩图像
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(screenshot, "jpg", baos);
byte[] imageData = baos.toByteArray();
// 发送图像大小和数据
dos.writeInt(imageData.length);
dos.write(imageData);
dos.flush();
// 控制帧率
long frameTime = System.currentTimeMillis() - startTime;
long delay = 1000 / FPS - frameTime;
if (delay > 0) {
Thread.sleep(delay);
}
}
} catch (IOException | InterruptedException e) {
System.out.println("客户端断开连接");
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void stop() {
running = false;
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.start();
}
}
客户端(查看屏幕)
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
public class Client extends JFrame {
private static final int DEFAULT_PORT = 8888;
private static final int BUFFER_SIZE = 1024 * 1024; // 1MB缓冲区
private Socket socket;
private DataInputStream dis;
private JLabel imageLabel;
private volatile boolean running = true;
public Client() {
initUI();
}
private void initUI() {
setTitle("屏幕分享查看端");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1024, 768);
setLocationRelativeTo(null);
imageLabel = new JLabel();
imageLabel.setHorizontalAlignment(JLabel.CENTER);
imageLabel.setVerticalAlignment(JLabel.CENTER);
JScrollPane scrollPane = new JScrollPane(imageLabel);
add(scrollPane, BorderLayout.CENTER);
// 快捷键退出
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
disconnect();
dispose();
}
}
});
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
disconnect();
}
});
}
public void connectToServer(String host, int port) {
try {
// 显示连接对话框
JDialog dialog = new JDialog(this, "连接服务器", true);
dialog.setLayout(new GridLayout(3, 2, 5, 5));
JTextField hostField = new JTextField(host == null ? "localhost" : host);
JTextField portField = new JTextField(String.valueOf(port == 0 ? DEFAULT_PORT : port));
dialog.add(new JLabel("服务器地址:"));
dialog.add(hostField);
dialog.add(new JLabel("端口:"));
dialog.add(portField);
JButton connectBtn = new JButton("连接");
JButton cancelBtn = new JButton("取消");
dialog.add(connectBtn);
dialog.add(cancelBtn);
connectBtn.addActionListener(e -> {
String serverHost = hostField.getText().trim();
int serverPort = Integer.parseInt(portField.getText().trim());
startReceiving(serverHost, serverPort);
dialog.dispose();
});
cancelBtn.addActionListener(e -> dialog.dispose());
dialog.pack();
dialog.setLocationRelativeTo(this);
dialog.setVisible(true);
} catch (Exception e) {
JOptionPane.showMessageDialog(this, "连接失败: " + e.getMessage());
e.printStackTrace();
}
}
private void startReceiving(String host, int port) {
new Thread(() -> {
try {
socket = new Socket(host, port);
dis = new DataInputStream(socket.getInputStream());
System.out.println("已连接到服务器: " + host + ":" + port);
while (running && !socket.isClosed()) {
// 读取图像数据
int size = dis.readInt();
// 限制最大图像大小,防止恶意数据
if (size > BUFFER_SIZE) {
System.err.println("图像数据过大,可能异常");
continue;
}
byte[] imageData = new byte[size];
dis.readFully(imageData);
// 转换并显示图像
BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageData));
if (image != null) {
updateImage(image);
}
}
} catch (IOException e) {
if (running) {
System.err.println("连接中断: " + e.getMessage());
JOptionPane.showMessageDialog(this, "连接已断开", "提示", JOptionPane.WARNING_MESSAGE);
}
} finally {
disconnect();
}
}).start();
}
private void updateImage(BufferedImage originalImage) {
SwingUtilities.invokeLater(() -> {
// 缩放图像以适应窗口
int maxWidth = 1024;
int maxHeight = 768;
double scaleX = (double) maxWidth / originalImage.getWidth();
double scaleY = (double) maxHeight / originalImage.getHeight();
double scale = Math.min(scaleX, scaleY);
int newWidth = (int) (originalImage.getWidth() * scale);
int newHeight = (int) (originalImage.getHeight() * scale);
Image scaledImage = originalImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
imageLabel.setIcon(new ImageIcon(scaledImage));
});
}
private void disconnect() {
running = false;
try {
if (socket != null) {
socket.close();
}
if (dis != null) {
dis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Client client = new Client();
client.setVisible(true);
// 如果提供了命令行参数,则直接连接
if (args.length > 0) {
client.connectToServer(args[0], args.length > 1 ?
Integer.parseInt(args[1]) : DEFAULT_PORT);
} else {
client.connectToServer(null, 0);
}
});
}
}
使用说明
编译和运行:
# 编译 javac Server.java Client.java # 运行服务端(共享屏幕) java Server # 运行客户端(查看屏幕) java Client # 或指定服务器地址 java Client 192.168.1.100 8888
功能特点
- 实时屏幕捕获:使用Java Robot类捕获屏幕
- 图像压缩:JPEG压缩减少网络传输数据量
- 多客户端支持:使用线程池支持多个客户端同时观看
- 自适应帧率:根据网络状况自动调整
- GUI界面:客户端提供简单的图形界面
- 自动缩放:图像自动适应窗口大小
改进方向
- 添加鼠标和键盘控制功能
- 实现屏幕区域选择
- 提供图像质量调节选项
- 添加音频传输功能
- 优化网络协议(如使用UDP)
- 实现断线重连机制
这个案例提供了一个完整的屏幕分享解决方案,可以根据实际需求进行调整和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播