文章目录

  • 1. 按
  • 2. tcping.exe
  • 2.1. 下载
  • 2.2. 使用方法
  • 2.3. 更多帮助
  • 2.3.1. Usage
  • 2.3.2. Examples
  • 3. Python代码
  • 3.1. 使用方法


1. 按

在Windows中,系统自带的ping命令往往只能检测ICMP端口的连接情况,如果服务器开启了防火墙并且禁用了ping命令,那么我们往往就没法进行检测网络联通情况了,另外ping命令也不能针对某一特定的端口进行测试。

本文介绍的这款工具不仅可以在服务器开启了防火墙并且禁用了ping命令的情况下进行测试与主机的联通情况,而且还能指定进行测试特定的端口。

在主流的Linux系统中,通过yum或者apt也可安装tcping,不过通过源安装的tcping只能显示单次检测的结果,也没有具体的连接时延。

现在我们介绍一下tcping工具并且用Python仿写一下相关功能,以便于在Linux上或其他平台上运行。

2. tcping.exe

在Windows上,可以直接下载tcping.exe,不需要再编写代码了。

2.1. 下载

2.2. 使用方法

  1. 使用CMD或者PowerShell转到相应的工作目录(存储exe文件的目录)下,然后执行:
./tcping coco56.top
  1. 用于测试本机与coco56.top所解析到的服务器的联通情况。
  2. 如下命令用于测试本机与114.114.114.114这台服务器的53号端口的连接情况
./tcping 114.114.114.114 53
  1. 另外为了方便使用,也可以把tcping.exe文件所在的目录追加到环境变量的Path值里。
  2. 在使用tcping时如需增加可选参数,请在tcping后直接增加,始终把主机和端口字段放在命令的最后
    如:
tcping -t sz.coco56.top 15273
tcping -t -6 1.coco56.top

2.3. 更多帮助

2.3.1. Usage

NAME
    tcping - simulate "ping" over tcp by establishing a connection to network hosts.
    Measures the time for your system to [SYN], receive the target's [SYN][ACK] and send [ACK].  Note that the travel time for
    the last ACK is not included - only the time it takes to be put on the wire a tthe sending end.

SYNOPSIS
    tcping [-tdsvf46] [-i interval] [-n times] [-w interval] [-b n] [-r times][-j depth] [--tee filename] [-f] destination [port]

DESCRIPTION
    tcping measures the time it takes to perform a TCP 3-way handshake (SYN, SYN/ACK, ACK) between itself and a remote host.
    The travel time of the outgoing final ACK is not included, only the (minimal) amount of time it has taken to drop it on
    the wire at the near end.  This allows the travel time of the (SYN, SYN/ACK) to approximate the travel time of the
    ICMP (request, response) equivalent.
    
OPTIONS
    -4      Prefer using IPv4

    -6      Prefer using IPv6

    -t      ping continuously until stopped via control-c

    -n count
            send _count_ pings and then stop.  Default 4.
    
    -i interval
            Wait _interval_ seconds between pings.  Default 1.  Decimals permitted.
    
    -w interval
            Wait _interval_ seconds for a response.  Default 2.  Decimals permitted.

    -d      include date and time on every output line
    
    -f      Force sending at least one byte in addition to making the connection.

    -g count
            Give up after _count_ failed pings.
    
    -b type
            Enable audible beeps.
            '-b 1' will beep "on down".  If a host was up, but now its not, beep.
            '-b 2' will beep "on up".  If a host was down, but now its up, beep.
            '-b 3' will beep "on change".  If a host was one way, but now its the other, beep.
            '-b 4' will beep "always".

    -c      only show output on a changed state
    
    -r count
            Every _count_ pings, we will perform a new DNS lookup for the host in case it changed.

    -s      Exit immediately upon a success.        

    -v      Print version and exit.

    -j      Calculate jitter.  Jitter is defined as the difference between the last response time and the historical average.

    -js depth
            Calculate jitter, as with -j but with an optional _depth_ argument specified. If _depth_ is specified tcping will
            use the prior _depth_ values to calculate a rolling average.

    --tee _filename_
            Duplicate output to the _filename_ specified.  Windows can still not be depended upon to have a useful command line 
            environment. Don't tease me, *nix guys.

    --append
            When using --tee, append to rather than overwrite the output file.
            
    --file
            Treat the "destination" option as a filename.  That file becomes a source of destinations, looped through on a
            line by line basis.  Some options don't work in this mode and statistics will not be kept.


    destination
            A DNS name, an IP address, or (in "http" mode) a URL.
            Do not specify the protocol ("http://") in "http" mode.  Also do not specify server port via ":port" syntax.
            For instance:   "tcping http://www.elifulkerson.com:8080/index.html" would fail
            Use the style:  "tcping www.elifulkerson.com/index.html 8080" instead.
                                
    port
            A numeric TCP port, 1-65535.  If not specified, defaults to 80.

    --header
            include a header with the command line arguments and timestamp.  Header is implied if using --tee.
            
HTTP MODE OPTIONS   
    -h      Use "http" mode.  In http mode we will attempt to GET the specified document and return additional values including
            the document's size, http response code, kbit/s.
    -u      In "http" mode, include the target URL on each output line.
    
    --post  Use POST instead of GET in http mode.
    --head  Use HEAD instead of GET in http mode.
    --get   Shorthand to invoke "http" mode for consistency's sake.

    --proxy-server _proxyserver_
            Connect to _proxyserver_ to request the url rather than the server indicated in the url itself.
    --proxy-port _port_
            Specify the numeric TCP port of the proxy server.  Defaults to 3128.
    --proxy-credentials username:password
            Specify a username:password pair which is sent as a 'Proxy-Authorization: Basic' header.


RETURN VALUE
    tcping returns 0 if all pings are successful, 1 if zero pings are successful and 2 for mixed outcome.

BUGS/REQUESTS
    Please report bugs and feature requests to the author via contact information on http://www.elifulkerson.com
    
AVAILABILITY
    tcping is available at http://www.elifulkerson.com/projects/tcping.php

2.3.2. Examples

C:\ tcping www.elifulkerson.com

Probing 64.22.103.201:80/tcp - Port is open - time=25.739ms
Probing 64.22.103.201:80/tcp - Port is open - time=21.842ms
Probing 64.22.103.201:80/tcp - Port is open - time=27.701ms
Probing 64.22.103.201:80/tcp - Port is open - time=27.489ms

Ping statistics for 64.22.103.201:80
     4 probes sent.
     4 successful, 0 failed.
Approximate trip times in milli-seconds:
     Minimum = 21.842ms, Maximum = 27.701ms, Average = 25.693ms
C:\tcping -h www.elifulkerson.com
** Requesting "" from www.elifulkerson.com:
(for various reasons, kbit/s is an approximation)

Probing 64.22.103.201:80/tcp - HTTP is open - time=31.288ms rcv_time=31.951 status=200 bytes=4052 kbit/s=~1014.554
Probing 64.22.103.201:80/tcp - HTTP is open - time=29.553ms rcv_time=30.947 status=200 bytes=4052 kbit/s=~1047.479
Probing 64.22.103.201:80/tcp - HTTP is open - time=29.871ms rcv_time=31.727 status=200 bytes=4052 kbit/s=~1021.728
Probing 64.22.103.201:80/tcp - HTTP is open - time=29.976ms rcv_time=36.002 status=200 bytes=4052 kbit/s=~900.393

Ping statistics for 64.22.103.201:80
     4 probes sent.
     4 successful, 0 failed.
Approximate trip times in milli-seconds:
     Minimum = 29.553ms, Maximum = 31.288ms, Average = 30.172ms

3. Python代码

tcping.py

import socket, sys
import time
import argparse
from argparse import RawTextHelpFormatter

VERSION = '1.0.1'

ping_cnt = 0
ping_success_cnt = 0
ping_fail_cnt = 0
ping_resp_min = 0
ping_resp_max = 0
ping_resp_avg = 0
ping_resp_total = 0


class MyParser(argparse.ArgumentParser):
	def error(self, message):
		sys.stderr.write('error: %s\n' % message)
		self.print_help()
		sys.exit(2)


# get ip from hostname
def host2ip(host):
	try:
		return socket.gethostbyname(host)
	except Exception:
		return False


# probing tcp port
def tcp(ip, port, timeout=2):
	sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	sk.settimeout(timeout)
	try:
		t1 = time.time()
		sk.connect((ip, port))
		t2 = time.time()
		sk.close()
		return True, int(round((t2 - t1) * 1000))
	except Exception:
		sk.close()
		return False, timeout * 1000


def format_tcp_result(results):
	if results[0]:
		return "Probing {}:{}/tcp - Port is open - time={}ms".format(ip, port, results[1])
	else:
		return "Probing {}:{}/tcp - No response - time={}ms".format(ip, port, results[1])


def statistic_tcp_result(results):
	global ping_cnt
	global ping_success_cnt
	global ping_fail_cnt
	global ping_resp_min
	global ping_resp_max
	global ping_resp_avg
	global ping_resp_total
	# total count
	ping_cnt += 1
	if results[0]:
		# success count
		ping_success_cnt += 1
		# min ping response time
		if ping_resp_min == 0:
			ping_resp_min = results[1]
		elif results[1] < ping_resp_min:
			ping_resp_min = results[1]
		# max ping respose time
		if results[1] > ping_resp_max:
			ping_resp_max = results[1]
		# average ping response time
		ping_resp_avg = round((ping_resp_total + results[1]) / float(ping_success_cnt), 3)
		ping_resp_total += results[1]
	else:
		# fail count
		ping_fail_cnt += 1

	return ping_cnt, ping_success_cnt, ping_fail_cnt, ping_resp_min, ping_resp_max, ping_resp_avg


if __name__ == "__main__":
	desc = '''--------------------------------------------------------------------------
Please see  for more introductions.
--------------------------------------------------------------------------'''

	example_text = '''examples:
    tcping coco56.top
    tcping 114.114.114.114 -t -p 53
    tcping zhangnq.com -n 10 -p 443 -i 5 -w 1
    \n
'''

	parser = MyParser(description=desc, formatter_class=RawTextHelpFormatter, epilog=example_text)
	parser.add_argument("destination", type=str, help="a DNS name, an IP address")
	parser.add_argument("-p", dest="port", type=int, default=80,
						help="a numeric TCP port, 1-65535. If not specified, defaults to 80.")
	parser.add_argument("-t", dest="is_continuously", action='store_true',
						help="ping continuously until stopped via control-c.")
	parser.add_argument("-n", dest="number", type=int, default=4, help="send count pings and then stop, default 4.")
	parser.add_argument("-i", dest="interval", type=int, default=1, help="wait seconds between pings, default 1.")
	parser.add_argument("-w", dest="wait", type=int, default=2, help="wait seconds for a response, default 2.")
	parser.add_argument("-v", "--version", action='version', version=VERSION, help="print version and exit.")
	args = parser.parse_args()

	ip = host2ip(args.destination)
	port = args.port
	if not ip:
		print("ERROR: Could not find host - %s, aborting" % args.destination)
		sys.exit(1)

	try:
		# continuously
		if args.is_continuously:
			print("")
			print("** Pinging continuously.  Press control-c to stop **")
			print("")
			while True:
				results = tcp(ip, port, args.wait)
				# print format result
				print(format_tcp_result(results))
				# start statistic
				statistic_tcp_result(results)

				time.sleep(args.interval)
		else:
			print("")
			for i in range(args.number):
				results = tcp(ip, port, args.wait)
				# print format result
				print(format_tcp_result(results))
				# start statistic
				statistic_tcp_result(results)

				time.sleep(args.interval)
	except KeyboardInterrupt:
		print("Control-C")
	finally:
		format_statistic_results = '''
Ping statistics for {}, port {}:
    Probes: send = {}, success = {}, fail = {} ({}% fail)
Approximate trip times:
    Minimum = {}ms, Maximum = {}ms, Average = {}ms
'''.format(ip, port, ping_cnt, ping_success_cnt, ping_fail_cnt, round(ping_fail_cnt / float(ping_cnt) * 100, 2),
		   ping_resp_min, ping_resp_max, ping_resp_avg)
		print(format_statistic_results)

3.1. 使用方法

需要先安装好Python3环境,具体参考:

  1. 将源码命名为tcping.py
  2. zabbix 网络设备延时大 如何监测 网络时延测试工具_HTTP

  3. 使用CMD或者PowerShell转到相应的工作目录(存储源码文件的目录)下,然后执行:
python .\tcping.py coco56.top

用于测试本机与coco56.top所解析到的服务器的联通情况。

zabbix 网络设备延时大 如何监测 网络时延测试工具_TCP_02

  1. 如下命令用于测试本机与114.114.114.114这台服务器的53号端口的连接情况
python .\tcping.py 114.114.114.114 -p 53

zabbix 网络设备延时大 如何监测 网络时延测试工具_TCP_03

  1. 参数介绍
必选参数:
destination a DNS name, an IP address
可选参数:
-h, --help show this help message and exit
-p PORT a numeric TCP port, 1-65535. If not specified, defaults to 80.
-t ping continuously until stopped via control-c.
-n NUMBER send count pings and then stop, default 4.
-i INTERVAL wait seconds between pings, default 1.
-w WAIT wait seconds for a response, default 2.
-v, --version print version and exit.