├── LICENSE ├── README.md ├── package.json └── ping.js /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Adam Paszke 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | tcp-ping 2 | ======== 3 | 4 | TCP ping utility for node.js. You can test if chosen address accepts connections at desired port and find out your latency. Great for service availability testing. 5 | 6 | ##### Why not `ping` wrapper? 7 | 8 | * It's much faster than `ping` tool (as soon as connection gets accepted, it's dropped and a new measure is conducted immediately), so there's no unnecessary waiting between requests. 9 | * It allows you to test a specific service, not the whole connection 10 | * Some servers drop ICMP echo without any response, even when online. TCP can work in such cases. 11 | 12 | ### Install 13 | 14 | ``` 15 | npm install tcp-ping 16 | ``` 17 | 18 | ### Functions 19 | 20 | ##### ping(options, callback) 21 | 22 | `options` is an object, which may contain several properties: 23 | 24 | * address (address to ping; defaults to `localhost`) 25 | * port (defaults to `80`) 26 | * timeout (in ms; defaults to 5s) 27 | * attempts (how many times to measure time; defaults to 10) 28 | 29 | `callback` should be a function with arguments in node convention - `function(err, data)`. 30 | 31 | Returned data is an object which looks like this: 32 | ```javascript 33 | { 34 | address: '46.28.246.123', 35 | port: 80, 36 | attempts: 10, 37 | avg: 19.7848844, 38 | max: 35.306233, 39 | min: 16.526067, 40 | results: 41 | [ 42 | { seq: 0, time: 35.306233 }, 43 | { seq: 1, time: 16.585919 }, 44 | ... 45 | { seq: 9, time: 17.625968 } 46 | ] 47 | } 48 | ``` 49 | 50 | ##### probe(address, port, callback) 51 | `callback` is a node style callback `function(err, data)`, where data is true if the server is available and false otherwise. 52 | 53 | ### Usage 54 | 55 | ```javascript 56 | var tcpp = require('tcp-ping'); 57 | 58 | tcpp.probe('46.28.246.123', 80, function(err, available) { 59 | console.log(available); 60 | }); 61 | 62 | tcpp.ping({ address: '46.28.246.123' }, function(err, data) { 63 | console.log(data); 64 | }); 65 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tcp-ping", 3 | "version": "0.1.1", 4 | "description": "A ping utility using TCP connection", 5 | "main": "ping.js", 6 | "scripts": { 7 | "test": "echo 0" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/wesolyromek/tcp-ping.git" 12 | }, 13 | "keywords": [ 14 | "ping", 15 | "util", 16 | "tcp", 17 | "availability" 18 | ], 19 | "author": "Adam Paszke", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/wesolyromek/tcp-ping/issues" 23 | }, 24 | "homepage": "https://github.com/wesolyromek/tcp-ping" 25 | } 26 | -------------------------------------------------------------------------------- /ping.js: -------------------------------------------------------------------------------- 1 | //The MIT License (MIT) 2 | // 3 | //Copyright (c) 2014 Adam Paszke 4 | // 5 | //Permission is hereby granted, free of charge, to any person obtaining a copy 6 | //of this software and associated documentation files (the "Software"), to deal 7 | //in the Software without restriction, including without limitation the rights 8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | //copies of the Software, and to permit persons to whom the Software is 10 | //furnished to do so, subject to the following conditions: 11 | // 12 | //The above copyright notice and this permission notice shall be included in all 13 | //copies or substantial portions of the Software. 14 | // 15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | //SOFTWARE. 22 | 23 | var net = require('net'); 24 | 25 | var ping = function(options, callback) { 26 | var i = 0; 27 | var results = []; 28 | options.address = options.address || 'localhost'; 29 | options.port = options.port || 80; 30 | options.attempts = options.attempts || 10; 31 | options.timeout = options.timeout || 5000; 32 | var check = function(options, callback) { 33 | if(i < options.attempts) { 34 | connect(options, callback); 35 | } else { 36 | var avg = results.reduce(function(prev, curr) { 37 | return prev + curr.time; 38 | }, 0); 39 | var max = results.reduce(function(prev, curr) { 40 | return (prev > curr.time) ? prev : curr.time; 41 | }, results[0].time); 42 | var min = results.reduce(function(prev, curr) { 43 | return (prev < curr.time) ? prev : curr.time; 44 | }, results[0].time); 45 | avg = avg / results.length; 46 | var out = { 47 | address: options.address, 48 | port: options.port, 49 | attempts: options.attempts, 50 | avg: avg, 51 | max: max, 52 | min: min, 53 | results: results 54 | }; 55 | callback(undefined, out); 56 | } 57 | }; 58 | 59 | var connect = function(options, callback) { 60 | var s = new net.Socket(); 61 | var start = process.hrtime(); 62 | s.connect(options.port, options.address, function() { 63 | var time_arr = process.hrtime(start); 64 | var time = (time_arr[0] * 1e9 + time_arr[1]) / 1e6; 65 | results.push({ seq: i, time: time }); 66 | s.destroy(); 67 | i++; 68 | check(options, callback); 69 | }); 70 | s.on('error', function(e) { 71 | results.push({seq: i, time: undefined, err: e }); 72 | s.destroy(); 73 | i++; 74 | check(options, callback); 75 | }); 76 | s.setTimeout(options.timeout, function() { 77 | results.push({seq: i, time: undefined, err: Error('Request timeout') }); 78 | s.destroy(); 79 | i++; 80 | check(options, callback); 81 | }); 82 | }; 83 | connect(options, callback); 84 | }; 85 | 86 | module.exports.ping = ping; 87 | 88 | module.exports.probe = function(address, port, callback) { 89 | address = address || 'localhost'; 90 | port = port || 80; 91 | ping({ address: address, port: port, attempts: 1, timeout: 5000 }, function(err, data) { 92 | var available = data.min !== undefined; 93 | callback(err, available); 94 | }); 95 | }; --------------------------------------------------------------------------------