`
java_mzd
  • 浏览: 583210 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

用UDP改良远程监控系统浅析

阅读更多

昨天的简单的计算已经告诉了我们

用TCP/IP来发送服务器桌面信息

服务器端发出一张图片大概需要的时间是200MS

(所谓发出,即打包完成到发送结束----调用输出流的flush()方法截止)

那我们其实能做到的也就是一秒钟发送5张图片

把服务器端发送图片的时间间隔改成200MS后

发现服务器端和客户端的屏幕传输还算是比较正常

能够及时看到服务器端的操作

 

基本改良咱是实现了

可是,咱不能满足

好吧,服务器端看电影,

客户端连接看看情况怎么样

额,客户端连上后

发现看到的电影里的人动作是不连贯的

WHY?

 

大伙都做到

电影是24帧每秒

而我们现在用TCP/IP就算用多线程

发挥网络最大能量(我们寝室的网络)

一秒也就传了5帧

这肯定是没办法正常看电影的

 

 

好了

现在问题提出来了

这种情况下

我们应该怎么样继续改良呢?

 

大伙都知道

TCP/IP是面向连接、可靠的传输

用TCP/IP只要网络是通的

咱就可以放心,不怕数据传布过去

过去了不怕它收不到

可是出来混,总得有代价嘛

其中的3次握手,差错重传等等功能开销都是很大的

TCP/IP提供了可靠性以后

传输速度啥的自然就受到了很大的影响

 

而UDP是无连接、不可靠的传输

它不需要提供负责的连接机制,不需要理会差错控制

UDP只管作死的一个劲往外发

至于收不收的到,收到多少,则是跟哥无关的事

 

在对实时性要求很多的情况下

我们都只想能尽可能的多传输一些数据过去

就顾不上考虑那么多差错控制啥的了

(你这边在看直播,如果传输有差错了,总不能暂停一下,回过头来再回放,然后继续吧?)

这个时候,适当的差错是可以容忍的

实时是第一位的

 

 

好吧

既然一堆废话解析已经说的差不多了

 

现在

就正式开始通过UDP传输来改造俺们滴远程控制系统

 

其实在原有系统的基础上

基本上可以什么都不用变

改几行代码就差不多了

 

首先

其他的操控类信息还是要求要准确的

所以我们继续保留原有的TCP/IP连接中的SOCKET连接

这一部分都不动

原有系统协议,构架都不动

 

我们要实施UDP传输改良性能

无非就是把图片传输这个绝对巨头用UDP处理掉

所以

我们需要该的代码其实只是如下

 

 

在服务器端,用UDP发送取代用SOCKET发送

	// 原有的用Socket发送图片的语句
	// clientInfo.getThread().sendMessage(_screenImageMessage);
              //用UDP发送的语句
	java.net.InetAddress clientIP = clientInfo.getIPaddress();
	int port=10000;//设置UDP端口为10000
	byte[] data = _screenImageMessage.pack();
	//封装为DatagramPacket
	DatagramPacket datapacke = new DatagramPacket(data,data.length,clientIP,port);
	//用来发送的DatagramSocket对象
	DatagramSocket castSocket = new DatagramSocket(11000);
	castSocket.send(datapacke);
	Log.recordTime("结束发送截屏图像");

 

在客户端,用UDP接收,取代用SOCKET接收,至于什么接收图片监听啥的都不用改了

把用UDP接收图片独立开一个线程,连接成功后,自动启动该线程

代码如下

public class ReciveScreenImageUDP extends Thread{
	Client _client;

	public ReciveScreenImageUDP(Client client) {
		_client = client;
	}
	public void run(){
		reciveUDPMessage();
	}

	public void reciveUDPMessage() {
		while (true) {
			try {
				DatagramSocket reciveImageSocket = new DatagramSocket(10000);
				// 定义缓冲区大小
				byte[] buffer = new byte[250000];
				DatagramPacket recivedPacket = new DatagramPacket(buffer,
						buffer.length);
				reciveImageSocket.receive(recivedPacket);
				// 接收完字节数组,开始解封,处理
				MessageHead message = UnpackMessageTools
						.unpackUDPimageMessage(buffer);
				_client.UDPMessageHandle(message);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

 

 

好了

问题出来了

 

咱又得开始说废话,讲道理,玩数学了

首先,我想大家应该明白一点

UDP中传输数据都是以DatagramPacket为单位传的

也就是说,我们接收也是一个pachet一个packet的来接收

那么,接收之前,我们怎么知道每个packet里面数据量的大小呢?

恭喜你

答对了

我们就是不知道

所以

我们必须用到缓冲区数组buffer来接收packet

buffer设置小了,那么剩下的那部分数据你是收不到的

人家发送方是不对你负责的,谁叫你Y自己小气,舍不得把buffer设大一点呢

于是有人说

我们就把buffer设大一点吧

你还真是大方。。。

只有一小杯水,你开一辆卡车去运,有必要吗?

 

我们得通过算数来解决问题的

 

要算数

我们首先得知道我们到底需要多大的缓冲区

才能够完整的接收packet,同时还不能太浪费,注意,我说的是太浪费

 

恩,那我们还是先知道每次对方传来的数据有多大吧

 

好,那我们就测试,每次生成的图片大概有多大

需要测试这个,无非就是,截个屏,化为数组,看下大小

测试代码如下,比较简单,就不废话来解释了

/**
 * 用来测试每次截屏生成图片大小的类
 * @author mzd
 */
public class ImageSizeTest {
	/**
	 * @param args
	 * @throws AWTException
	 */
	public void getImageSize() throws AWTException {
		java.awt.Robot rb = new java.awt.Robot();
		Dimension d = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
		Rectangle rt = new Rectangle(0, 0, (int) d.getWidth(), (int) d
				.getHeight());
		byte[] data = null;
		for (int i = 0; i < 1000; i++) {
			BufferedImage image = rb.createScreenCapture(rt);
			data = bufferedImageTobytes(image);
			System.out.println(i + "--------图片--------->" + data.length);
		}
	}

	private byte[] bufferedImageTobytes(BufferedImage image) {
		BufferedImage bImage = new BufferedImage(image.getWidth(null), image
				.getHeight(null), BufferedImage.TYPE_INT_ARGB);
		Graphics bg = bImage.getGraphics();
		bg.drawImage(image, 0, 0, null);
		bg.dispose();
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			ImageIO.write(bImage, "jpeg", out);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return out.toByteArray();
	}

	public static void main(String args[]) throws Exception {
		ImageSizeTest test = new ImageSizeTest();
		test.getImageSize();
	}

}

 

 

我运行了1000次来观测,在这里就不可能贴出1000次的结果了

随机截取一部分吧

299--------图片--------->184001

300--------图片--------->183878

301--------图片--------->183825

302--------图片--------->183796

303--------图片--------->183710

304--------图片--------->183705

305--------图片--------->183705

306--------图片--------->183827

307--------图片--------->183827

308--------图片--------->183827

309--------图片--------->183921

310--------图片--------->184064

311--------图片--------->184040

312--------图片--------->183792

313--------图片--------->183809

314--------图片--------->183900

315--------图片--------->183867

316--------图片--------->183789

317--------图片--------->183871

318--------图片--------->183691

319--------图片--------->183685

320--------图片--------->183666

321--------图片--------->183666

322--------图片--------->183666

323--------图片--------->183666

324--------图片--------->183666

325--------图片--------->183666

326--------图片--------->183666

327--------图片--------->183666

328--------图片--------->183961

329--------图片--------->183961

330--------图片--------->183961

331--------图片--------->183961

332--------图片--------->183961

333--------图片--------->184059

很明显,我们发现每个图片的应该在200000左右

为了保险起见,

我们把缓冲区再设大点

250000

 

 

好了

废话完了

代码改完了

咱执行一次看看?

 

java.net.SocketException: The message is larger than the maximum supported by the underlying transport: Datagram send failed

    at java.net.PlainDatagramSocketImpl.send(Native Method)

    at java.net.DatagramSocket.send(DatagramSocket.java:612)

    at cn.javaeye.java_mzd.Monitor.Server.CastScreenImageUDP.castScreenImage(CastScreenImageUDP.java:49)

    at cn.javaeye.java_mzd.Monitor.Server.CastScreenImageUDP.run(CastScreenImageUDP.java:22)

    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)

    at java.lang.Thread.run(Thread.java:619)

 

 

我勒个去……………………

 

 

辛辛苦苦,看我废话半天

改了半天

结果不行?

 这也太恶心

太丢脸了

 

我没办法

别急

 

咱再慢慢分解

首先

咱看报的错误

The message is larger than the maximum supported by the underlying transport: Datagram send failed

 

大家英语都比我好

都看的明白

简单的说

就是传的文件比Datagram允许的大了

 

这是怎么回事?

人家几个G都能传

我这么小个图片竟然不能传?

TCP/IP都能传

UDP还不能传?

恭喜你答对了

TCP/IP能传

你用UDP直接用packet还就是传不了

(注意,我是说直接用packet

这是为什么呢?

还记得前面我废话过TCP/IP可以差错控制什么的嘛?

TCP的时候

协议会把大文件分块成许多小块

发表路由发送至目的地后

再通过标识来重组,对没有成功发送的提供差错控制

完成重传

UDP不提供此功能(当然,你可以直接去完善,那不是我今天讨论的内容)

 

好了

回到正题

为什么UDP会传不了呢?

我们知道

不管用UDP还是TCP最后得被封住成IP数据包

而一个IP数据报的总长度只是用16位来表示

16位,什么概念呢

也就是最多可以放64KB的数据

再回头看看我们截屏的图片大小

200KB

所以……………………

 

好了

休息会

下期分解

JAVA中图片有损压缩

 

 

 

分享到:
评论

相关推荐

    UDP远程监控系统.docx

    在远程监控系统中,UDP 可能是更适合的选择,特别是在需要处理大量并发连接、实时性要求高或者需要穿透NAT(Network Address Translation)的场景。 首先,让我们分析一下TCP和UDP在远程监控系统中的应用场景和优劣...

    C# udp远程监控摄像头工具.rar

    在本项目中,我们主要关注的是使用C#编程语言实现基于UDP协议的远程监控摄像头功能。UDP(User Datagram Protocol)是一种无连接的、不可靠的传输层协议,适合于需要实时性但对数据完整性要求不高的应用,如视频监控...

    基于Udp的远程屏幕监控

    【基于UDP的远程屏幕监控】...总的来说,基于UDP的远程屏幕监控系统利用C++Builder的开发能力,结合网络编程和图形处理技术,实现了高效、实时的屏幕共享功能。这种技术在远程协助、监控、教育等多个领域都有广泛应用。

    基于JAVA CS远程监控系统软件的实现(源代码+WORD论文文档论文).zip

    基于JAVA C/S远程监控系统软件突破了空间的限制,使用者不用亲临,在自己的电脑面前就能轻松的实现对被监控端机器的监控。本系统采用Java网络编程和Java图形编程实现。笔者在开发过程中将网络技术与远程监控理论基础...

    论文研究-UDP协议在Web远程电源监控系统中的应用 .pdf

    本文所提到的Web远程电源监控系统,是一个典型的使用UDP协议的场景。这种系统通常需要将电源设备的数据实时传输到远程监控中心,以便监控人员可以实时了解设备的电源状态。由于实时性要求非常高,系统往往需要在尽...

    基于JAVACS远程监控系统软件的实现.pdf

    JAVACS远程监控系统中使用了多种网络通信协议,包括TCP/IP、UDP以及Telnet。TCP/IP是互联网上最广泛使用的网络协议,提供可靠的数据传输。UDP则是一种无连接的协议,适用于传输不需要可靠传输保证的数据。Telnet是一...

    基于android的远程监控系统综合课程设计(完整版)

    ### 基于Android的远程监控系统综合课程设计的关键知识点 #### 一、设计背景与概述 本设计针对当前视频监控技术的需求和发展趋势,提出了一个基于Android系统的远程监控方案。随着科技的进步,尤其是网络技术和...

    基于VC的远程远程监控系统

    在IT领域,基于VC(Visual C++)的远程监控系统是一种常见的应用,它结合了计算机视觉、网络通信和多媒体处理技术,使得用户可以实时监控远端的摄像头画面。本项目提供的是一个服务器端与客户端(接受端)的完整工程...

    用C++语言编写的远程监控系统.zip

    【标题】"用C++语言编写的远程监控系统"揭示了这个项目的核心是利用C++编程语言构建一个能够实现远程监控功能的系统。C++是一种强大的、面向对象的编程语言,广泛应用于系统软件、游戏开发、实时金融系统以及各种...

    基于LabVIEW的远程监控系统设计与实现

    基于LabVIEW的远程监控系统设计与实现,是一个集成了现代通信技术、计算机科学与控制理论的综合项目。本文档详细介绍了如何利用LabVIEW这一强大的图形化编程环境来构建一个高效、可靠的远程监控系统,适用于工业自动...

    UDP.rar_UDP 远程控制_udp远程控制

    4. **实际应用**:UDP远程控制可能被用在设备监控、智能家居系统、分布式计算等场景,允许用户远程控制和管理设备或系统。 5. **开发注意事项**: - **防火墙配置**:确保服务器的UDP端口在防火墙中开放,允许...

    基于Android的远程监控系统的设计与实现.pdf

    "基于Android的远程监控系统的设计与实现" 本文主要介绍了一种基于Android的远程监控系统的设计与实现。该系统旨在解决当前数控机床操控具有局限性的问题,提供了一种功能强大、操作简单的远程监控解决方案。 首先...

    javaTCP、UDP和RMI实现的远程监控,可以语音通信

    javaTCP、UDP和RMI实现的远程监控,可以语音通信javaTCP、UDP和RMI实现的远程监控,可以语音通信

    远程监控系统VC++

    在这个场景中,我们关注的是一个使用VC++(Visual C++)开发的远程监控系统。VC++是Microsoft开发的一个集成开发环境,支持C++语言,提供了丰富的库和工具,适合构建复杂的桌面应用程序,包括系统级和网络通信程序。...

    udp 和tcp结合视频监控系统.zip

    /// 发送器所使用的编码 /// public Encoding Encoding { get; set; } /// /// 启动发送器 /// /// &lt;returns&gt;UDP发送器 public UdpSender Start() { if (!IsRunning) { IsRunning = ...

    基于VC++的远程桌面监控系统

    综上所述,基于VC++的远程桌面监控系统涉及的技术范围广泛,包括但不限于MFC库的使用、客户端-服务器通信、UDP协议、屏幕捕捉与图像处理、网络编程以及可能的视频处理技术。在实际开发过程中,还需要考虑安全性、...

    C#远程监控源代码C#远程监控源代码

    在C#中,我们可以利用.NET Framework或.NET Core提供的丰富的库和API来构建远程监控系统。 1. **基础架构**:构建远程监控系统的第一步是设计合适的架构。通常包括客户端(监测和发送请求)、服务器端(接收请求并...

    基于UDP的聊天室监控系统

    【基于UDP的聊天室监控系统】是一个利用UDP协议实现的实时通信系统,它不仅具备基本的聊天功能,还集成了服务器对客户端的监控能力。在这个系统中,服务器不仅可以接收和发送消息,还可以监控客户端的屏幕活动,实现...

    C#远程监控视频源码

    对于开发者来说,理解和掌握这些知识点,能够帮助他们构建自己的远程监控系统,满足特定需求。同时,源码分析和学习也是一个很好的实践机会,可以帮助提升编程技能,尤其是网络编程和多媒体处理方面的能力。

Global site tag (gtag.js) - Google Analytics