专业编程基础技术教程

网站首页 > 基础教程 正文

JS模拟的Ping程序 (Web Ping)(js模拟实现new)

ccvgpt 2024-07-19 12:48:47 基础教程 14 ℃

JS虽然发送不了真正Ping的ICMP数据包,但Ping的本质仍然是请求/回复的时间差,我们可以试图去请求站点的某个不存在资源,根据返回错误的时间,我们就可以计算出延时的时间差了。在本例,我们尝试访问指定站点下的一个不存在的图片文件(文件名是个随机数),以致onerror事件发生,这个过程大致就是网络上的延时差。

当然,实际过程中会复杂的多。HTTP1.1协议第一次访问时需要一个TCP连接的过程,要经过3次握手之后才开始HTTP通信,因此第一次就要慢一些。如果是ping一个域名,那还要包括域名解析的时间;其次,在理论上,之后的Request和Response是一个TCP-AP包和TCP-ACK包。但如果访问的是一个不存在的资源,服务器有可能会返回一个HTTP重定向,这时客户端就要再请求一次,直到重定向的页面数据收到后,才触发onerror事件,这其中的时间就要长的多了。 如果服务器404的数据长度大于数据包的MTU值,IP协议还会分包传输,这样延时就会成倍的增加。

JS模拟的Ping程序 (Web Ping)(js模拟实现new)

另外一个可能的情况就是,请求一个不存在的主机,理应超时才对。但有可能运营商的DNS返回一个广告网站的IP,例如互联星空,以至于ping的很流畅。

附:源码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>HTTP Ping</title>
<style>
html
{
	height: 100%;
	overflow: hidden;
}
body
{
	background: #000;
	color: #C0C0C0;
	font: bold 14px 'Lucida Console';
	height: 100%;
	margin: 0 0 0 5px;
}
#divContent
{
	height: 90%;
	overflow: auto;
}
#txtTimeout
{
	width: 40px;
}
button
{
	margin-left: 10px;
}
</style>
</head>
<body>
<div id="divInput">
	<span>Host:</span>
	<input id="txtURL" type="text" />
	<span>Timeout:</span>
	<input id="txtTimeout" type="text" value="2000" />
	<input id="btnSwitch" type="button" value="Start" onclick="handleClick()" />
	<hr/>
</div>
<div id="divContent"></div>
<script>
var iSeq = 0;
var iSent, iReply;
var iSum, iMax, iMin;
var sURL, iTimeout;
var bRunning = false;
var tick, tid;
function reply()
{
	if(!bRunning || this.seq != iSeq)
		return;
	/*
	 * 取消超时计时
	 */
	clearTimeout(tid);
	++iReply;
	var delay = new Date - tick;
	iSum += delay;
	if(delay > iMax)
		iMax = delay;
	if(delay < iMin)
		iMin = delay;
	println("Reply from " +
			sURL +
			" time" +
			((delay<1)? ("<1") : ("="+delay)) +
			"ms");
	tid = setTimeout(ping, Math.max(1000-delay, 1000));
}
function ping()
{
	tick = +new Date;
	++iSent;
	tid = setTimeout(timeout, iTimeout);
	var oImg = new Image;
	oImg.onload = reply;
	oImg.onerror = reply;
	oImg.seq = ++iSeq;
	// 发送请求
	oImg.src = sURL + "/" + tick + ".html";
}
function timeout()
{
	if(!bRunning)
		return;
	println("Request timed out.");
	ping();
}
</script>
<script>
function $(v){return document.getElementById(v)}
var oBtn = $("btnSwitch");
var oContent = $("divContent");
var txtURL = $("txtURL");
txtURL.value = location.host;
function handleClick()
{
	if(bRunning)
	{
		/*
		 * 停止
		 */
		oBtn.value = "Start";
		bRunning = false;
		clearTimeout(tid);
		/*
		 * 统计结果
		 */
		var lost = iSent - iReply;
		println(" ");
		println("Ping statistics for " + sURL + ":");
		println("  Packets: Sent = " +
				iSent +
				", Received = " +
				iReply +
				", Lost = " +
				lost +
				" (" +
				Math.round(lost / iSent * 100) +
				"% loss),");
		if(iReply == 0)
			return;
		println("Approximate round trip times in milli-seconds:");
		println("  Minimum = " +
				iMin +
				"ms, Maximum = " +
				iMax +
				"ms, Average = " +
				Math.round(iSum / iReply) +
				"ms");
	}
	else
	{
		/*
		 * 开始
		 */
		sURL = txtURL.value;
		if(sURL.length == 0)
			return;
		if(sURL.substring(0,7).toLowerCase() != "http://")
			sURL = "http://" + sURL;
		iTimeout = parseInt($("txtTimeout").value, 10);
		if(isNaN(iTimeout))
			iTimeout = 2000;
		if(iTimeout < 1000)
			iTimeout = 1000;
		oBtn.value = "Stop ";
		bRunning = true;
		iSent = 0;
		iReply = 0;
		iSum = 0;
		iMax = -1;
		iMin = 1e9;
		cls();
		println("Pinging " + sURL + ":");
		println(" ");
		ping();
	}
}
function println(str)
{
	var div = document.createElement("div");
	if(div.innerText != null)
		div.innerText = str;
	else
		div.textContent = str;
	oContent.appendChild(div);
	oContent.scrollTop = oContent.scrollHeight;
}
function cls()
{
	oContent.innerHTML = "";
}
</script>
</body>
</html>

Tags:

最近发表
标签列表