是否可以从 Javascript ping 服务器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4282151/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to ping a server from Javascript?
提问by Chuck Callebs
I'm making a web app that requires that I check to see if remote servers are online or not. When I run it from the command line, my page load goes up to a full 60s (for 8 entries, it will scale linearly with more).
我正在制作一个需要检查远程服务器是否在线的网络应用程序。当我从命令行运行它时,我的页面加载时间长达 60 秒(对于 8 个条目,它将随着更多条目线性扩展)。
I decided to go the route of pinging on the user's end. This way, I can load the page and just have them wait for the "server is online" data while browsing my content.
我决定走用户端ping的路线。这样,我可以加载页面并让他们在浏览我的内容时等待“服务器在线”数据。
If anyone has the answer to the above question, or if they know a solution to keep my page loads fast, I'd definitely appreciate it.
如果有人对上述问题有答案,或者如果他们知道让我的页面快速加载的解决方案,我将不胜感激。
采纳答案by Chuck Callebs
I have found someone that accomplishes this with a very clever usage of the native Image
object.
我发现有人通过非常巧妙地使用本机Image
对象来实现这一点。
From their source, this is the main function (it has dependences on other parts of the source but you get the idea).
从他们的来源来看,这是主要功能(它依赖于来源的其他部分,但你明白了)。
function Pinger_ping(ip, callback) {
if(!this.inUse) {
this.inUse = true;
this.callback = callback
this.ip = ip;
var _that = this;
this.img = new Image();
this.img.onload = function() {_that.good();};
this.img.onerror = function() {_that.good();};
this.start = new Date().getTime();
this.img.src = "http://" + ip;
this.timer = setTimeout(function() { _that.bad();}, 1500);
}
}
This works on all types of servers that I've tested (web servers, ftp servers, and game servers). It also works with ports. If anyone encounters a use case that fails, please post in the comments and I will update my answer.
这适用于我测试过的所有类型的服务器(网络服务器、ftp 服务器和游戏服务器)。它也适用于端口。如果有人遇到失败的用例,请在评论中发帖,我会更新我的答案。
Update: Previous link has been removed. If anyone finds or implements the above, please comment and I'll add it into the answer.
更新:上一个链接已被删除。如果有人发现或实现了上述内容,请发表评论,我会将其添加到答案中。
Update 2: @trante was nice enough to provide a jsFiddle.
更新 2:@trante 提供了一个 jsFiddle。
http://jsfiddle.net/GSSCD/203/
http://jsfiddle.net/GSSCD/203/
Update 3: @Jonathon created a GitHub repo with the implementation.
更新 3:@Jonathon 创建了一个带有实现的 GitHub 存储库。
https://github.com/jdfreder/pingjs
https://github.com/jdfreder/pingjs
Update 4: It looks as if this implementation is no longer reliable. People are also reporting that Chrome no longer supports it all, throwing a net::ERR_NAME_NOT_RESOLVED
error. If someone can verify an alternate solution I will put that as the accepted answer.
更新 4:看起来这个实现不再可靠。人们还报告说 Chrome 不再支持这一切,从而引发net::ERR_NAME_NOT_RESOLVED
错误。如果有人可以验证替代解决方案,我会将其作为已接受的答案。
回答by Nils Holgersson
Ping is ICMP, but if there is any open TCP port on the remote server it could be achieved like this:
Ping 是 ICMP,但如果远程服务器上有任何打开的 TCP 端口,则可以这样实现:
function ping(host, port, pong) {
var started = new Date().getTime();
var http = new XMLHttpRequest();
http.open("GET", "http://" + host + ":" + port, /*async*/true);
http.onreadystatechange = function() {
if (http.readyState == 4) {
var ended = new Date().getTime();
var milliseconds = ended - started;
if (pong != null) {
pong(milliseconds);
}
}
};
try {
http.send(null);
} catch(exception) {
// this is expected
}
}
回答by jerjer
you can try this:
你可以试试这个:
put ping.htmlon the server with or without any content, on the javascript do same as below:
将ping.html放在有或没有任何内容的服务器上,在 javascript 上做如下相同的操作:
<script>
function ping(){
$.ajax({
url: 'ping.html',
success: function(result){
alert('reply');
},
error: function(result){
alert('timeout/error');
}
});
}
</script>
回答by Eugene
You can't directly "ping" in javascript. There may be a few other ways:
您不能在 javascript 中直接“ping”。可能还有其他几种方式:
- Ajax
- Using a java applet with isReachable
- Writing a serverside script which pings and using AJAX to communicate to your serversidescript
- You might also be able to ping in flash (actionscript)
- 阿贾克斯
- 使用带有isReachable的 java 小程序
- 编写一个服务器端脚本,它 ping 并使用 AJAX 与您的服务器端脚本通信
- 你也可以在 flash 中 ping (actionscript)
回答by Epeli
You can't do regular ping in browser Javascript, but you can find out if remote server is alive by for example loading an image from the remote server. If loading fails -> server down.
您无法在浏览器 Javascript 中执行常规 ping,但您可以通过例如从远程服务器加载图像来确定远程服务器是否处于活动状态。如果加载失败 -> 服务器关闭。
You can even calculate the loading time by using onload-event. Here's an examplehow to use onload event.
您甚至可以使用 onload-event 计算加载时间。这是如何使用 onload 事件的示例。
回答by Antony Woods
Pitching in with a websocket solution...
使用 websocket 解决方案投球...
function ping(ip, isUp, isDown) {
var ws = new WebSocket("ws://" + ip);
ws.onerror = function(e){
isUp();
ws = null;
};
setTimeout(function() {
if(ws != null) {
ws.close();
ws = null;
isDown();
}
},2000);
}
回答by user456733
To keep your requests fast, cache the server side results of the ping and update the ping file or database every couple of minutes(or however accurate you want it to be). You can use cron to run a shell command with your 8 pings and write the output into a file, the webserver will include this file into your view.
为了保持您的请求快速,缓存 ping 的服务器端结果并每隔几分钟更新一次 ping 文件或数据库(或者您希望它有多准确)。您可以使用 cron 运行带有 8 个 ping 的 shell 命令并将输出写入文件,网络服务器会将此文件包含在您的视图中。
回答by Ohad
If what you are trying to see is whether the server "exists", you can use the following:
如果您想查看服务器是否“存在”,则可以使用以下命令:
function isValidURL(url) {
var encodedURL = encodeURIComponent(url);
var isValid = false;
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodedURL + "%22&format=json",
type: "get",
async: false,
dataType: "json",
success: function(data) {
isValid = data.query.results != null;
},
error: function(){
isValid = false;
}
});
return isValid;
}
This will return a true/false indication whether the server exists.
这将返回一个真/假指示服务器是否存在。
If you want response time, a slight modification will do:
如果你想要响应时间,稍微修改一下就可以了:
function ping(url) {
var encodedURL = encodeURIComponent(url);
var startDate = new Date();
var endDate = null;
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodedURL + "%22&format=json",
type: "get",
async: false,
dataType: "json",
success: function(data) {
if (data.query.results != null) {
endDate = new Date();
} else {
endDate = null;
}
},
error: function(){
endDate = null;
}
});
if (endDate == null) {
throw "Not responsive...";
}
return endDate.getTime() - startDate.getTime();
}
The usage is then trivial:
用法很简单:
var isValid = isValidURL("http://example.com");
alert(isValid ? "Valid URL!!!" : "Damn...");
Or:
或者:
var responseInMillis = ping("example.com");
alert(responseInMillis);
回答by sebilasse
There are many crazy answers here and especially about CORS -
这里有很多疯狂的答案,尤其是关于 CORS -
You could do an http HEAD request (like GET but without payload). See https://ochronus.com/http-head-request-good-uses/
您可以执行 http HEAD 请求(如 GET 但没有有效负载)。见https://ochronus.com/http-head-request-good-uses/
It does NOT need a preflight check, the confusion is because of an old version of the specification, see Why does a cross-origin HEAD request need a preflight check?
它不需要预检,混淆是因为规范的旧版本,请参阅 为什么跨域 HEAD 请求需要预检?
So you could use the answer above which is using the jQuery library (didn't say it) but with
所以你可以使用上面的答案,它使用 jQuery 库(没有说)但是
type: 'HEAD'
--->
--->
<script>
function ping(){
$.ajax({
url: 'ping.html',
type: 'HEAD',
success: function(result){
alert('reply');
},
error: function(result){
alert('timeout/error');
}
});
}
</script>
Off course you can also use vanilla js or dojo or whatever ...
当然,您也可以使用 vanilla js 或 dojo 或其他任何东西...
回答by the Tin Man
The problem with standard pings is they're ICMP, which a lot of places don't let through for security and traffic reasons. That might explain the failure.
标准 ping 的问题在于它们是 ICMP,出于安全和交通原因,很多地方都不允许通过。这或许可以解释失败的原因。
Ruby prior to 1.9 had a TCP-based ping.rb
, which will run with Ruby 1.9+. All you have to do is copy it from the 1.8.7 installation to somewhere else. I just confirmed that it would run by pinging my home router.
1.9 之前的 Ruby 有一个基于 TCP 的ping.rb
,它将与 Ruby 1.9+ 一起运行。您所要做的就是将它从 1.8.7 安装复制到其他地方。我刚刚确认它可以通过 ping 我的家用路由器来运行。