-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The first viable version of TCP Ping, and close #1
- Loading branch information
0 parents
commit 932a00c
Showing
8 changed files
with
483 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Set default behaviour, in case users don't have core.autocrlf set. | ||
* text=auto | ||
|
||
# These files are text and should be normalized (convert crlf => lf) | ||
*.cs text diff=csharp | ||
*.xaml text | ||
*.csproj text | ||
*.sln text | ||
*.tt text | ||
*.ps1 text | ||
*.cmd text | ||
*.msbuild text | ||
*.md text | ||
|
||
# Images should be treated as binary | ||
# (binary is a macro for -text -diff) | ||
*.png binary | ||
*.jpeg binary | ||
|
||
*.sdf binary | ||
*.dat binary |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
## Ignore Visual Studio temporary files, build results, and | ||
## files generated by popular Visual Studio add-ons. | ||
|
||
# User-specific files | ||
*.suo | ||
*.user | ||
*.sln.docstates | ||
|
||
# Build results | ||
[Dd]ebug/ | ||
[Dd]ebugPublic/ | ||
[Rr]elease/ | ||
x64/ | ||
build/ | ||
bld/ | ||
[Bb]in/ | ||
[Oo]bj/ | ||
|
||
# Roslyn cache directories | ||
*.ide/ | ||
|
||
# MSTest test Results | ||
[Tt]est[Rr]esult*/ | ||
[Bb]uild[Ll]og.* | ||
|
||
#NUNIT | ||
*.VisualState.xml | ||
TestResult.xml | ||
|
||
# Build Results of an ATL Project | ||
[Dd]ebugPS/ | ||
[Rr]eleasePS/ | ||
dlldata.c | ||
|
||
*_i.c | ||
*_p.c | ||
*_i.h | ||
*.ilk | ||
*.meta | ||
*.obj | ||
*.pch | ||
*.pdb | ||
*.pgc | ||
*.pgd | ||
*.rsp | ||
*.sbr | ||
*.tlb | ||
*.tli | ||
*.tlh | ||
*.tmp | ||
*.tmp_proj | ||
*.log | ||
*.vspscc | ||
*.vssscc | ||
.builds | ||
*.pidb | ||
*.svclog | ||
*.scc | ||
|
||
# Chutzpah Test files | ||
_Chutzpah* | ||
|
||
# Visual C++ cache files | ||
ipch/ | ||
*.aps | ||
*.ncb | ||
*.opensdf | ||
*.sdf | ||
*.cachefile | ||
|
||
# Visual Studio profiler | ||
*.psess | ||
*.vsp | ||
*.vspx | ||
|
||
# TFS 2012 Local Workspace | ||
$tf/ | ||
|
||
# Guidance Automation Toolkit | ||
*.gpState | ||
|
||
# ReSharper is a .NET coding add-in | ||
_ReSharper*/ | ||
*.[Rr]e[Ss]harper | ||
*.DotSettings.user | ||
|
||
# JustCode is a .NET coding addin-in | ||
.JustCode | ||
|
||
# TeamCity is a build add-in | ||
_TeamCity* | ||
|
||
# DotCover is a Code Coverage Tool | ||
*.dotCover | ||
|
||
# NCrunch | ||
_NCrunch_* | ||
.*crunch*.local.xml | ||
|
||
# MightyMoose | ||
*.mm.* | ||
AutoTest.Net/ | ||
|
||
# Web workbench (sass) | ||
.sass-cache/ | ||
|
||
# Installshield output folder | ||
[Ee]xpress/ | ||
|
||
# DocProject is a documentation generator add-in | ||
DocProject/buildhelp/ | ||
DocProject/Help/*.HxT | ||
DocProject/Help/*.HxC | ||
DocProject/Help/*.hhc | ||
DocProject/Help/*.hhk | ||
DocProject/Help/*.hhp | ||
DocProject/Help/Html2 | ||
DocProject/Help/html | ||
|
||
# Click-Once directory | ||
publish/ | ||
|
||
# Publish Web Output | ||
*.[Pp]ublish.xml | ||
*.azurePubxml | ||
## TODO: Comment the next line if you want to checkin your | ||
## web deploy settings but do note that will include unencrypted | ||
## passwords | ||
#*.pubxml | ||
|
||
# NuGet Packages Directory | ||
packages/* | ||
## TODO: If the tool you use requires repositories.config | ||
## uncomment the next line | ||
#!packages/repositories.config | ||
|
||
# Enable "build/" folder in the NuGet Packages folder since | ||
# NuGet packages use it for MSBuild targets. | ||
# This line needs to be after the ignore of the build folder | ||
# (and the packages folder if the line above has been uncommented) | ||
!packages/build/ | ||
|
||
# Windows Azure Build Output | ||
csx/ | ||
*.build.csdef | ||
|
||
# Windows Store app package directory | ||
AppPackages/ | ||
|
||
# Others | ||
sql/ | ||
*.Cache | ||
ClientBin/ | ||
[Ss]tyle[Cc]op.* | ||
~$* | ||
*~ | ||
*.dbmdl | ||
*.dbproj.schemaview | ||
*.pfx | ||
*.publishsettings | ||
node_modules/ | ||
|
||
# RIA/Silverlight projects | ||
Generated_Code/ | ||
|
||
# Backup & report files from converting an old project file | ||
# to a newer Visual Studio version. Backup files are not needed, | ||
# because we have git ;-) | ||
_UpgradeReport_Files/ | ||
Backup*/ | ||
UpgradeLog*.XML | ||
UpgradeLog*.htm | ||
|
||
# SQL Server files | ||
*.mdf | ||
*.ldf | ||
|
||
# Business Intelligence projects | ||
*.rdl.data | ||
*.bim.layout | ||
*.bim_*.settings | ||
|
||
# Microsoft Fakes | ||
FakesAssemblies/ | ||
|
||
# LightSwitch generated files | ||
GeneratedArtifacts/ | ||
_Pvt_Extensions/ | ||
ModelManifest.xml | ||
|
||
# JetBrains Rider | ||
.idea/ | ||
*.sln.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio 2013 | ||
VisualStudioVersion = 12.0.0.0 | ||
MinimumVisualStudioVersion = 10.0.0.1 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TcpPing", "TcpPing\TcpPing.csproj", "{5FF939DD-7129-4F04-A419-5623F8E66054}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{5FF939DD-7129-4F04-A419-5623F8E66054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{5FF939DD-7129-4F04-A419-5623F8E66054}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{5FF939DD-7129-4F04-A419-5623F8E66054}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{5FF939DD-7129-4F04-A419-5623F8E66054}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<Properties StartupItem="TcpPing/TcpPing.csproj"> | ||
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" /> | ||
<MonoDevelop.Ide.Workbench /> | ||
<MonoDevelop.Ide.DebuggingService.Breakpoints> | ||
<BreakpointStore /> | ||
</MonoDevelop.Ide.DebuggingService.Breakpoints> | ||
<MonoDevelop.Ide.DebuggingService.PinnedWatches /> | ||
</Properties> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Net.Sockets; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace TcpPing | ||
{ | ||
internal class Program | ||
{ | ||
private static void Main(string[] args) | ||
{ | ||
try | ||
{ | ||
Driver(args); | ||
} | ||
catch (Exception ex) | ||
{ | ||
Console.WriteLine(ex.Message); | ||
} | ||
} | ||
|
||
private static void Driver(IReadOnlyList<string> args) | ||
{ | ||
if (args[0].Split(':').Length != 2) | ||
{ | ||
throw new ArgumentException("Please specify hostname and port in hostname:port format."); | ||
} | ||
|
||
var hostname = args[0].Split(':')[0]; | ||
var ip = GetEndPointIp(hostname); | ||
|
||
var port = GetPortNumber(args[0].Split(':')[1]); | ||
|
||
var endPoint = new IPEndPoint(ip, port); | ||
|
||
Console.WriteLine( | ||
$"Pinging {hostname}:{port} [{ip}:{port}]:"); | ||
|
||
var pingResults = new List<double?>(); | ||
|
||
foreach (var delay in TcpPing(endPoint)) | ||
{ | ||
pingResults.Add(delay); | ||
Console.WriteLine( | ||
delay.HasValue | ||
? $"time = {delay.Value:0.00} ms" | ||
: "Request timed out"); | ||
} | ||
|
||
var validDelays = pingResults | ||
.Where(t => t.HasValue) | ||
.Select(t => t.Value) | ||
.ToList(); | ||
Console.WriteLine( | ||
$"--- {ip}:{port} ping statistics ---"); | ||
|
||
if (validDelays.Any()) | ||
Console.WriteLine( | ||
$"round-trip min/avg/max = {validDelays.Min():0.00}/{validDelays.Max():0.00}/{validDelays.Average():0.00} ms"); | ||
|
||
var sentCount = pingResults.Count; | ||
var receivedCount = pingResults.Count(t => t.HasValue); | ||
var lossCount = sentCount - receivedCount; | ||
var lossRate = lossCount / sentCount; | ||
if (lossCount > 0) | ||
Console.WriteLine( | ||
$"{sentCount} packets transmitted, {receivedCount} packets received, {100 * lossRate:0.0}% packet loss"); | ||
} | ||
|
||
// ReSharper disable once SuggestBaseTypeForParameter | ||
private static IEnumerable<double?> TcpPing(IPEndPoint endPoint) | ||
{ | ||
for (var i = 0; i < 4; i++) | ||
{ | ||
using (var socket = | ||
new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) | ||
{ | ||
Blocking = true | ||
} | ||
) | ||
{ | ||
var stopWatch = new Stopwatch(); | ||
|
||
stopWatch.Start(); | ||
// ReSharper disable once AccessToDisposedClosure | ||
var taskConnect = Task.Run(() => socket.Connect(endPoint)); | ||
var taskCountDown = Task.Run(() => Thread.Sleep(TimeOutLimit)); | ||
Task.WaitAny(taskConnect, taskCountDown); | ||
stopWatch.Stop(); | ||
socket.Close(); | ||
|
||
var delay = stopWatch.Elapsed.TotalMilliseconds; | ||
|
||
yield return delay < TimeOutLimit.TotalMilliseconds ? (double?) delay : null; | ||
|
||
Thread.Sleep(Interval); | ||
} | ||
} | ||
} | ||
|
||
private static IPAddress GetEndPointIp(string hostname) | ||
{ | ||
IPAddress ip = null; | ||
if (IPAddress.TryParse(hostname, out ip)) return ip; | ||
|
||
try | ||
{ | ||
ip = Dns.GetHostAddresses(hostname).First(); | ||
} | ||
catch (Exception) | ||
{ | ||
throw new ArgumentException($"Failed to look up host address for {hostname}."); | ||
} | ||
return ip; | ||
} | ||
|
||
private static int GetPortNumber(string portString) | ||
{ | ||
try | ||
{ | ||
var port = ushort.Parse(portString); | ||
return port; | ||
} | ||
catch (Exception ex) | ||
{ | ||
throw new ArgumentException($"Invalid port number {portString}."); | ||
} | ||
} | ||
|
||
private static TimeSpan TimeOutLimit => TimeSpan.FromSeconds(2); | ||
|
||
private static TimeSpan Interval => TimeSpan.FromSeconds(1); | ||
} | ||
} |
Oops, something went wrong.