C# 实现局域网的windows环境下的桌面分享

C#实现屏幕共享(UDP+redis) 采用C#,基于udp+redis实现低延迟的屏幕共享(同屏,投屏) 阅读详情

       先谈需求,本demo源于实验室的师兄们找工作的时候,针对有些公司会监视多屏幕的情况,突发奇想自己写了一个小demo来分享屏幕,随手写的使用价值不大~在本机测试效果不错,但是跨机效果很一般,不知道是不是路由器的问题。另没有对接收发送的数据进行校验,只是比较基础的实现。为什么说是局域网,因为数据传输效果太糟糕,理论远程也是可以的,没有试。只贴出了处理代码,界面代码和编译后的结果我上传github了,可以查看

服务器代码:

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
using System.Drawing;
using System.IO;

namespace screen_server
{
    class Server
    {
        private string localIP;
        private Bitmap screenNow;
        private string[] terminalList;
        private int listenPort;
        private int screenHeight;
        private int screenWidth;
        private bool isWork;
        private byte[] buffer;
        private string errorMessage;
        private Socket server;


        public Server(int listenPort)
        {
            screenWidth  = Screen.PrimaryScreen.Bounds.Width;
            screenHeight = Screen.PrimaryScreen.Bounds.Height;
            ScreenNow = new Bitmap(screenWidth, screenHeight);
            IsWork = false;

            this.listenPort = listenPort;
            //获取本地ip地址
            try
            {
                string HostName = Dns.GetHostName(); //得到主机名
                IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
                for (int i = 0; i < IpEntry.AddressList.Length; i++)
                {
                    if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                    {
                        //限制了实验室网段或者学校内网
                        if (IpEntry.AddressList[i].ToString().Contains("192.168.199") || IpEntry.AddressList[i].ToString().Contains("114.213"))
                        {
                            LocalIP = IpEntry.AddressList[i].ToString();
                            break;
                        }
                    }
                }
                if (LocalIP == null)
                    LocalIP = "";
            }
            catch (Exception ex)
            {
                errorMessage =  ex.Message;
                showErrorMessage();
            }
        }
        
        public string[] TerminalList { get => terminalList; set => terminalList = value; }
        public string LocalIP { get => localIP; set => localIP = value; }
        public Bitmap ScreenNow { get => screenNow; set => screenNow = value; }
        public bool IsWork { get => isWork; set => isWork = value; }

        public void showErrorMessage()
        {
            
        }

        public void startService()
        {
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ip = IPAddress.Parse(LocalIP);
            server.Bind(new IPEndPoint(ip, listenPort));
            server.Listen(10);
            Thread myThread = new Thread(ListenClientConnect);
            myThread.Start();
            Thread catchScreen = new Thread(screenUpdate);
            catchScreen.Start();
            IsWork = true;
        }

        private void ListenClientConnect()
        {
            while (true)
            {
                Socket client = server.Accept();
                Thread sendThread = new Thread(sendPic);
                sendThread.Start(client);
            }
        }

        private void screenUpdate()
        {
            Bitmap temp = new Bitmap(screenWidth, screenHeight);
            Graphics gc = Graphics.FromImage(temp);
            while (true)
            {
                gc.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(screenWidth, screenHeight));
                imgtoBytes(temp);
                screenNow = new Bitmap(temp);
                GC.Collect();
                Thread.Sleep(500);
            }
        }
        
        private void imgtoBytes(Bitmap bitmap)
        {
            MemoryStream ms = new MemoryStream();
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
            buffer = ms.GetBuffer();
            ms.Close();
        }

        private void sendPic(object clientSocket)
        {
            Socket client = (Socket)clientSocket;
            byte[] receiveBuffer = new byte[1024];
            byte[] imageCopy;
            while (true)
            {
                try
                {
                    //客户端返回确认后才发送新的数据
                    int receiveLength = client.Receive(receiveBuffer);
                    imageCopy = new byte[buffer.Length];
                    Buffer.BlockCopy(buffer, 0, imageCopy, 0, buffer.Length);
                    byte[] dataLength = BitConverter.GetBytes(imageCopy.Length);
                    client.Send(dataLength);
                    receiveLength = client.Receive(receiveBuffer);
                    client.Send(imageCopy);
                }
                catch
                {
                    //do Nothing,just break
                }
            }
        }
    }
}

客户端代码:

using System;
using System.Drawing;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;

namespace screenClient
{
    public partial class clientWin : Form
    {
        public clientWin()
        {
            InitializeComponent();
        }

        private void startButton_Click(object sender, EventArgs e)
        {
            string ipPort = configBox.Text;
            string[] config = ipPort.Split(':');
            if (config.Length!=2)
            {
                MessageBox.Show("请输入正确的ip和端口号!");
                return;
            }
            string IP = config[0];
            int port = Convert.ToInt32(config[1]);
            try
            {
                IPAddress ip = IPAddress.Parse(IP);
                Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientSocket.Connect(new IPEndPoint(ip, port));
                Thread imageUpdate = new Thread(update);
                imageUpdate.Start(clientSocket);
            }
            catch (Exception ex)
            {
                MessageBox.Show("建立连接失败,请重试!");
            }
        }

        private void update(object clientSocket)
        {
            Socket client = (Socket)clientSocket;
            int receiveNumber;
            byte[] buffer;
            byte[] image;
            while (true)
            {
                //先发送一个确认连接包
                buffer = new byte[1];
                buffer[0] = 1;
                client.Send(buffer);
                //先记录数据的大小,再申请对应大小的缓冲区
                buffer = new byte[4];
                receiveNumber = client.Receive(buffer);
                int dataLength =  BitConverter.ToInt32(buffer, 0);
                client.Send(buffer);
                buffer = new byte[4096];
                image = new byte[dataLength];
                GC.Collect();
                int offset = 0;
                while (offset != dataLength)
                {
                    receiveNumber = client.Receive(buffer);
                    Buffer.BlockCopy(buffer, 0, image, offset, receiveNumber);
                    offset += receiveNumber;
                }
                pictureBox.Image = getBitmap(image);
            }
        }

        private Bitmap getBitmap(byte[] bytesData)
        {
            MemoryStream ms1 = new MemoryStream(bytesData);
            Bitmap bm = (Bitmap)Image.FromStream(ms1);
            ms1.Close();
            return bm;
        }
    }
}

使用方式:
       首先打开服务器端,填入端口号(建议10000~65534),然后点击监听端口按钮(这个时候会给出本机ip,但我限定了局域网192.168.199和114.213前缀,可自行查询ip或者修改代码),再启动服务即可。提供了浏览功能~客户端填入ip地址和端口号即可。

windows屏幕分享方案 200毫秒内延迟效果图 阅读详情

相关推荐

如何实现共享屏幕标注功能?

  在视频会议系统中,经常会有这样的需求:参会人员A共享了自己的屏幕给大家观看,人员B则需要在屏幕图像上做标注,并且希望所有的与会人员都能看到他做的标注。 这个功能通常被称为共享屏幕标注、或屏幕标注、或带标绘功能的远程桌面。 一.实现方案    将这个功能拆解开来,实际上就是 远程桌面 + 电子白板,我们可以在远程桌面的控件上叠加一个背景透明的电子白板就可以实现这样的效果。    接下来,我们尝试使用 OMCS 的远程桌面组件和电子白板组件,来实现这个功能。具体而言,我们在 OMCS...

qq_38082146的博客 874

C# winform屏幕共享 Stocket网络通信-菜鸟入门 详细注释

简单的winform屏幕共享,实现服务端和多个客户端之间的屏幕共享,自动获取局域网ip和端口号,详细代码注释,希望对stocket网络通信的小伙伴有帮助

C# 实现轻量级局域网P2P文件传输系统

P2P文件传输是一种去中心化的网络通信范式,其核心在于节点自主发现、NAT穿透与分块可靠传输。在局域网场景下,传统HTTP或共享文件夹方案常面临速度瓶颈与配置复杂问题,而基于C#的轻量级实现可兼顾开发效率与运行时零依赖特性。通过自定义UDP打洞协调、内存映射式大文件分块读取、SHA256+MD5双校验机制及WPF线程安全更新,系统在不依赖云服务、不安装额外运行库的前提下,实现毫秒级节点发现与千兆带宽利用率。该方案特别适用于企业内网快速传大文件、教学演示及嵌入式协作工具开发等工程实践场景。

dianlu5775的博客 542

windows下实现屏幕分享(C#)

采用UDP广播进行数据的传输,实现windows下进行低延迟的屏幕共享。 开发语言:C# 第三方组件:Redis 1.实现思路 总体流程图 DGIS.DesktopShare实现windows下屏幕分享低延迟功能,按照服务执行位置由三部分构成:发起端、接收端、缓存端。 通过UDP广播实现发起端和接收端的通讯,是为了尽量的减少通讯负载和降低延迟。众...

weixin_33885253的博客 4783

C#实现局域网P2P文件传输系统:零配置、断点续传、NAT穿透

P2P文件传输是一种去中心化点对点通信技术,其核心原理是通过节点间直接交换数据块降低服务器负载与带宽依赖。在内网隔离、临时协作、隐私敏感等现实场景中,传统云盘或HTTP直传因策略限制或第三方介入而失效,此时轻量级P2P方案展现出独特技术价值。C#凭借Windows生态适配性、NAT穿透可控性及资源调度确定性,成为构建高可靠局域网P2P系统的优选语言;结合Tracker协调与UDP打洞机制,可在无公网IP、禁用广播的受限网络中实现98.2%直连成功率与毫秒级节点发现。本文聚焦可落地的工程实践,覆盖文件分块校验

dianlu5775的博客 543

C# 借助WinPcap实现EtherCAT IO实时控制(告别专用硬件)

本文介绍了一种利用C#和WinPcap库实现低成本EtherCAT主站的方案,无需专用硬件即可对IO模块进行实时控制。文章详细阐述了从环境搭建、PDO映射配置到实时数据读写的完整流程,并探讨了该方案在运动控制、系统集成等场景的扩展应用与性能优化技巧。

mac99的博客 735

C#局域网桌面共享

该例涉及到的知识点有局域网文件传输、桌面截屏、图片压缩等,实现的功能是局域网桌面共享软件

Visual C++实战开发:从MFC框架到现代桌面应用构建

在Windows平台开发领域,Visual C++作为原生开发的核心工具链,其重要性不言而喻。其核心原理基于微软基础类库(MFC)框架,通过消息驱动机制和文档/视图架构,实现了高效的桌面应用程序开发。这一技术价值在于能够构建高性能、高稳定性的系统级应用,广泛应用于工业控制、企业管理系统、传统桌面软件等场景。在开发实践中,开发者常需处理如“microsoft visual c++ redistributable”运行时依赖问题,并利用Visual Studio强大的调试工具进行问题排查。本文聚焦于如何通过实例

weixin_34209851的博客 319

基于Tcp穿越的Windows远程桌面(远程桌面管理工具)

基于Tcp穿越的Windows远程桌面(远程桌面管理工具) 1.《C# WinForm 跨线程访问控件(实用简洁写法)》 2.《基于.NET环境,C#语言 实现 TCP NAT》 3.《基于Tcp穿越的Windows远程桌面(远程桌面管理工具)》 距离上一篇文章《基于.NET环境,C#语言 实现 TCP ...

anguona0764的博客 673

Windows局域网桌面实时共享工具(C#开发,UDP直传,实测170ms延迟)

这是一款专为局域网环境设计的Windows桌面共享小工具,用C#编写,基于WinForm界面,开箱即用。核心功能是捕获本机屏幕并以UDP广播方式低延迟推送到同一局域网内的其他设备,实测端到端延迟约170毫秒,适合内部演示、远程协作或教学场景。程序内置完整服务端模块(DGIS.DesktopShare.Service)、屏幕捕获组件(Oraycn.MCapture.dll),以及Redis通信支持、JSON序列化、基础网络通信(ESBasic.dll)和UDP传输能力。依赖库已全部打包,包括ServiceSt

eee77的博客 266

C# Winform实现局域网即时通信:Socket编程实战与踩坑指南

网络编程中,Socket是构建实时通信系统的核心基础。理解TCP字节流特性是关键,因为数据在传输中并无天然边界,粘包与半包问题因此成为开发者必须跨越的坎。通过自定义消息头+消息体的协议设计,可以有效拆分数据包。C#语言结合Winform框架,利用async/await异步编程模型,能够在不阻塞UI线程的情况下处理Socket通信,同时解决跨线程操作控件的安全性问题。这类技术广泛应用于局域网即时通信、上位机与工控设备交互、企业内部工具开发等场景。从同步阻塞到异步回调,再到async/await,选择合适的So

weixin_33997389的博客 472

Windows桌面应用开发选型:原生、跨平台与云桌面怎么选

Windows桌面应用开发通常指在Windows上构建带图形界面的客户端程序,其底层涉及窗口消息循环、UI渲染、控件体系和运行时依赖。原生框架如WinForms、WPF、WinUI 3直接依托系统或.NET栈,跨平台方案如Electron、Tauri、Qt、Flutter通过自带或借用渲染引擎实现多端一致,云桌面与应用虚拟化则把窗口渲染和交付搬到远端。技术价值在于按数据安全、交付范围、团队技能与体验要求匹配路径,避免把性能、体积、许可证和并发带宽等问题误判为框架优劣。企业内网客户端、工业上位机、外协办公、多

weixin_34343000的博客 309

C#桌面客户端自动更新:从版本比对到增量更新的完整实现

在桌面应用开发中,软件版本迭代与自动升级是提升用户体验、降低维护成本的关键环节。自动更新机制通常涉及版本号比对、文件差异检测、下载与校验等基础原理,其核心目标是让客户端在后台安全地完成自我升级。常见的实现方案包括全量更新与增量更新,其中增量更新通过MD5等校验算法精准定位变更文件,显著减少网络流量。在实际工程实践中,开发者需考虑文件占用处理、断点续传、多版本兼容及异常回滚等问题。本文以C# WinForm/WPF为例,深入讲解如何设计并实现一套可靠的桌面客户端自动更新系统,帮助独立开发者与企业工具链摆脱手动

weixin_33831196的博客 474

windows下实现屏幕分享(C#)-附件资源

windows下实现屏幕分享(C#)-附件资源

局域网IP排查实战:ipconfig、ping、arp、nbtstat命令组合全解析

局域网管理中,IP地址是设备通信的基础,而高效定位IP问题离不开对命令提示符下DOS命令的灵活运用。ipconfig负责展示本机IP配置,ping用于探测对端连通性,arp解析IP与MAC地址映射,nbtstat反查主机名,tracert追踪路由路径。这些命令按“查配置—探网关—验对端—理缓存”的顺序组合,能快速构建完整的网络故障证据链。对于运维新手和桌面支持工程师,掌握这套查询命令,不仅可应对IP冲突、DHCP租约失效、防火墙拦截等常见场景,还能通过批处理脚本实现自动化信息收集,提升日常网络排查效率,真正

weixin_34280237的博客 390

基于VC6.0+MFC的桌面考试系统设计与实现

Windows桌面应用开发中,MFC作为C++的经典界面框架,通过封装Win32 API和消息映射机制,让开发者能高效构建对话框类程序。它强调窗口与控件的交互逻辑,适合表单密集型场景。在实际工程中,常配合Access数据库和ADO技术实现数据持久化,利用随机组卷算法和自动判分逻辑提升业务效率。这类技术栈尤其适用于教学管理、在线考试等轻量级部署环境,具有无需额外运行库、拷贝即用的特点。本文将围绕一个基于VC6.0+MFC的桌面考试系统,详细拆解其登录权限、题库管理、随机组卷、在线答题与自动判分等核心模块的实现

weixin_33804582的博客 457

如何让局域网用户访问你的Unity WebGL游戏?IIS部署+IP配置教程

本文详细讲解了如何通过IIS部署Unity WebGL游戏,并配置局域网IP访问,实现多设备协同测试。教程涵盖从Unity发布设置、IIS服务器搭建、IP绑定到防火墙配置等关键步骤,并提供了MIME类型配置、常见故障排查等进阶优化方案,帮助开发团队高效进行内部测试与原型展示。

metal的博客 422

C#远程桌面共享、屏幕差异传输

WinFrom抓取屏幕,把屏幕分成多个块,提取变化的块,并使用Tcp协议传输;实现远程桌面共享,投屏

上一篇: jupyter notebook运行两个小时后崩溃以及百度搜索总会跳回主页
下一篇: 分布式数据库之Oracle相关
乐莫新相知
博客等级 码龄12年 13粉丝 16原创
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值