In C# verify the ping utility - c#

From C# console application i had open the command prompt and checked the ping utility.
string aptracommand;
aptracommand = "/C ping 10.38.2.73";
Process.Start(#"cmd",aptracommand);
Now , i need to apply a conditional statement if ping request time out then it should say "Not able to connect" and if its able to ping then need to show "Server is up"

You can use Ping class for this purpose. As stated below:
using System.Net.NetworkInformation;
var ping = new Ping();
var reply = ping.Send("10.38.2.73", 60 * 1000); // 1 minute time out (in ms)
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Server is up");
}
else
{
Console.WriteLine("Server is down");
}
You can reduce the time out value to quickly check if server is up or down.

use this instead
Ping pingSender = new Ping ();
byte[] data = Encoding.ASCII.GetBytes ("test");
int timeout = 100;
PingReply reply = pingSender.Send("127.0.0.1", timeout, data);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address.ToString());
Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
}

I think you will need to capture the output, check for the existence of time out string and then take the decision based on that.
Capturing the Output

Related

PingReply is null when using SendAsync

I am building a server selection screen and have a bunch of IP addresses that need to be pinged in order to know the remote hosts are reachable and to establish a TCP connection afterwards to request their data (like connected playerCount and MOTD, think of Minecraft Multiplayer Selection screen, you don't connect to the game, only requesting data from the endpoint).
The problem is that Ping is always unsuccessful, because the PingReply is null.
For generic use cases, I have wrapped the call with an event that gets fired when the Ping Reply is received back to the sender.
public static async void PingNET(string address, int timeOutMs, System.Action<PingReply> onCompleted)
{
await Task.Run(() => { //to continue unity main thread, start new thread
AutoResetEvent waiter = new AutoResetEvent(false);
var pingSender = new System.Net.NetworkInformation.Ping ();
// call handler when PingCompleted event is raised
pingSender.PingCompleted += (sender, e) =>
{
Debug.LogError ("Error and reply is always null! See: Error is null?: "
+ (e.Error == null) + " - Reply is null?: " + (e.Reply == null));
// If the operation was canceled, display a message to the user.
if (e.Cancelled) {
Debug.LogWarning("Ping canceled.");
}
// If an error occurred, display the exception to the user.
if (e.Error != null) {
Debug.LogError ("Ping failed:" + e.Error.ToString ());
}
if(onCompleted != null)
onCompleted(e.Reply);
};
// Send the ping asynchronously (uses internal new thread,
// so program does not freeze until reply received)
pingSender.SendAsync(address, timeOutMs, waiter);
});
}
Unity Test Runner Unit Test:
[Test]
public void PingTest(){
List<string> addresses = new List<string>(){
"127.0.0.1", "localhost", "www.stackoverflow.com", "www.google.com"
};
for (int i = 0; i < addresses.Count; i++)
{
Ping(addresses[i]);
}
}
private void Ping(string address){
NetworkUtils.PingNET(address, 10000, new System.Action<PingReply>((PingReply reply) => {
if (reply != null && reply.Status == IPStatus.Success)
{
Debug.Log($"Address: {reply.Address.ToString()}");
Debug.Log($"RoundTrip time: {reply.RoundtripTime}");
}
else //this gets called obviously
{
Debug.LogError("PING REPLY ERROR " + reply?.Status);
}
}));
}
Side Info: (Not directly tied to the question)
The reason why I use Ping in the first place is to prevent freeze (deadlock) on the client when the server goes offline while the connection is still tied to it and requesting data to the now unavailable remote host endpoint of the server. I could notify all connected clients that the server is shutting down, but this of course will not work when the server immediately lost connection to the internet.
So all in all, when the ping fails, it should handle in the UI logic to display the server is unreachable. Otherwise if it was successful, a TCP connection to the server is created to send a request. The server that listens on the same port sends a response with the data (playerCount, MOTD, etc.). After that, the client deseralizes the byte array to the datatypes and fires an event, which is subscribed by the UI to gather the deserealized data and display those.
The sending/receiving part with UI already works, just the ping not.
Is this process overcomplicated? Let me know if it could be simplified.
Any help is greatly appreciated.

Why can't I use the TCP client to send two message? (continuation)

This is a continuation of an earlier question. I am starting a new thread so that I can show the latest complete server and client code, including all of the suggestions I have received in that thread and on Reddit.
I am running under Windows 7 Pro.
I have a very simple TCP server written in Python. It creates a socketserver object and waits for a message. When one arrives, the server prints it to its console and sends a simple acknowledgement back through the same port.
The client sends a numbered message to the server, waits for an acknowledgement, and displays it. It then asks the user if another message should be sent.
The first message is sent and acknowledged successfully. On the client side, it appears that the second message is sent successfully; the call to the network stream's Write() method succeeds. But when the Read() message is called to get the acknowledgement, an exception is thrown: "An established connection was aborted by the software in your host machine."
Here is the server code:
import json
import threading
import socketserver
import time
with open('CAPS_TWMS_config.json', 'rt') as c:
caps_config = json.load(c)
# We are listening on this port and all defined IP addresses
# listenPort = 5001
listenPort = caps_config["listen_port"]
# Were to send the information to.
clientIPAddress = '127.0.0.1' # socket.gethostbyname('client')
# clientPort = 12345
clientPort = caps_config["send_port"]
dsnName = caps_config["dsn_name"]
# Message sequence number
sequence_num = 1
exit_app = False
class ListenSocketHandler(socketserver.BaseRequestHandler):
"""
The RequestHandler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def __init__(self, request, client_address, this_server):
socketserver.BaseRequestHandler.__init__(self, request, client_address, this_server)
self.timeout = 10
def handle(self):
try:
data = self.request.recv(1024).decode()
# print (str.format("dataString[21]: {0}; dataString[24:26]: {1}", data[21], data[24:26]))
print ('ListenSocketHandler recv()-> "%s"' % data)
print ('ListenSocketHandler recv().length-> "%d"' % len(data))
if len(data) > 0:
self.request.send("I got a message!".encode())
return
except Exception as value:
print('ListenSocketHandler - %s' % str(value))
return
class ListenServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
"""
The multi-threaded server that will spawn threads running the Socket Handler for each
connection
"""
pass
if __name__ == '__main__':
try:
# Create the Server Handler for connections to this computer listening on all IP addresses,
# change '' to 'x.x.x.x' to listen on a specific IP network. This class will listen for messages # from CAPS.
server = ListenServer(('', listenPort), ListenSocketHandler)
ip, port = server.server_address
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
# Exit the server thread when the main thread terminates
server_thread.setDaemon(True)
server_thread.start()
while not exit_app:
time.sleep(1)
print ('Out of main loop.')
server.shutdown()
server.server_close()
except Exception as value:
print("Failed to do something: %s", str(value))
Here is the client code:
private void button1_Click(object sender, EventArgs e)
{
TcpClient client = new TcpClient();
try
{
client.Connect("127.0.0.1", 5001);
NetworkStream stream = client.GetStream();
int messageCount = 1;
while (true)
{
// Translate the passed message into ASCII and store it as a Byte array.
string message = string.Format("This is message {0}", messageCount++);
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
// Receive the TcpServer.response.
// Buffer to store the response bytes.
data = new Byte[1024];
// String to store the response ASCII representation.
String responseData = String.Empty;
// Read the first batch of the TcpServer response bytes.
Int32 receivedCount = 0;
int sleepCount = 0;
while (receivedCount == 0)
{
receivedCount = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, receivedCount);
if (receivedCount == 0)
{
Thread.Sleep(250);
if (sleepCount++ > 20)
{
MessageBox.Show("Response timeout.");
break;
}
}
}
if (MessageBox.Show("Reply: " + responseData + " Try again?", "Try again?", MessageBoxButtons.YesNo) == DialogResult.No)
{
break;
}
}
client.Close();
}
catch (Exception ex)
{
MessageBox.Show("Failed to do something with TcpClient: " + ex.Message);
}
}
In your code, every time when a new client is connected it is reading the data and acknowledges to client and handler is closed(i.e. return) immediately after the following statement
self.request.send("I got a message!".encode())
return
Hence the connection is closed.and further command from client is not sending. You can wait in a loop to receive and acknowledge.

How to quickly ping all ip addresses in a network? [duplicate]

This question already has answers here:
find all ip address in a network
(5 answers)
Closed 8 years ago.
So I am making a network scanner in c# to show all connected devices to the same network as you. The way I am doing this is by doing a ping command on all IP's from 192.168.0.1 to 192.168.0.255.
private void IPlook_Tick(object sender, EventArgs e)
{
Properties.Settings.Default.nextIP += 1;
if (Properties.Settings.Default.nextIP >= 255)
{
IPlook.Stop();
}
string IP = "192.168.0." + Properties.Settings.Default.nextIP.ToString();
CurIP.Text = IP;
//See if online
try
{
Ping ping = new Ping();
PingReply pingreply = ping.Send(IP);
if (pingreply.Status == IPStatus.Success)
{
string Hostname = Dns.GetHostByAddress(IP).HostName;
dataGridView1.Rows.Add(Hostname, IP, "");
}
else
{
}
}
catch (Exception er)
{
MessageBox.Show("Something Went Wrong", "Error Alert", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
This is working fine but the problem is it is taking a very long time and making the program laggy. I have set the interval on the timer to 50.
Any help is appreciated.
Legitimate
How about firing them all off at once (from an async method):
IPAddress start = IPAddress.Parse("192.168.1.1");
var bytes = start.GetAddressBytes();
var leastSigByte= start.GetAddressBytes().Last();
var range= 255 - leastSigByte;
var pingReplyTasks = Enumerable.Range(leastSigByte,range)
.Select(x=>{
var p = new Ping();
var bb = start.GetAddressBytes();
bb[3] = (byte)x;
var destIp = new IPAddress(bb);
var pingResultTask = p.SendPingAsync(destIp);
return new{pingResultTask, addr = destIp};
})
.ToList();
await Task.WhenAll(pingReplyTasks.Select(x=>x.pingResultTask));
foreach(var pr in pingReplyTasks)
{
var tsk = pr.pingResultTask;
var pingResult = tsk.Result; //we know these are completed tasks
var ip = pr.addr;
Console.WriteLine("{0} : {1}",ip,pingResult.Status);
}
You probably don't want to ping addresses ending in 0 or 255.
You are running the pings one after the other. This means that you must wait for the timeout to expire 255 times. Start multiple pings at the same time. Using await would make a lot of sense here.
Also, unblock the UI thread so that the UI is not frozen while this is in progress. Many techniques are available for doing that. await happens to solve this problem as well.
I don't see why you are using a timer. If there is no reason for that simply delete all timer stuff. Use a loop.
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
// Can build your list of IPs using a for loop
List<IPAddress> ips = new List<IPAddress>
{
new IPAddress(new byte[] {192, 168, 0, 1}),
new IPAddress(new byte[] {192, 168, 0, 2}),
// More ips in this list.
};
// Exactly what do you do with initiated tasks will depend on your specific scenario.
List<Task> tps = new List<Task>();
foreach(var ip in ips)
{
tps.Add(InitiatePing(ip));
}
// Needed so that console app doesn't exit..
Console.ReadLine();
}
private static async Task InitiatePing(IPAddress ip)
{
// Note, this API is different from SendAsync API you are using
// You may also want to reuse Ping instance instead of creating new one each time.
var result = await new Ping().SendPingAsync(ip);
// Process your result here, however you want.
Console.WriteLine(result.Address + "-" + result.Status + "-" + result.RoundtripTime);
}
}
}
Well if I'm reading your code correctly you're allowing the timer to fire 255 times and are pinging exactly one computer in each execution. I'm not sure why you're using a Settings class to store the current iteration number.
You could loop over 1 to 255 and launch each Ping request asynchronously using the Ping.SendAsync method. There is no need for a timer.
See also this question and answers/comments about broadcast pinging.

Ping reply taking too long/not working

When using Ping in correlation with PingReply to check the status of an IP Address and it's ports for and imported text list how do you launch a code to skip the current one and move onto the next one?
PingReply reply = ping.Send("IP", "PORT");
Specifically
PingReply reply = ping.Send("174.69.75.251", "41968");
There is no response at all, it just freezes the application so you cant check the reply status if its successful.
Going to a list of proxies I want to check if they're valid and able to be connected to a webBrowser1 control so I have the following code to send the request for the IP Address and Port to check if it will accept connections.
This is the whole code for the loop and everything, I have added what has been suggested by two people and excluded the TCPClient one with /* */ heres the code for the button:
private void button2_Click(object sender, EventArgs e)
{
numberProx = Convert.ToInt32(textBox1.Lines.Length.ToString());
proxyList = textBox1.Text.Split(new Char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
while (i < numberProx)
{
string currentProxy = proxyList[i++].ToString();
try
{/*
TcpClient reply2 = new TcpClient();
reply2.ConnectAsync(currentProxy.Split(':')[0],
Convert.ToInt32(currentProxy.Split(':')[1]));
if (reply2.Connected)
{
textBox2.AppendText(currentProxy + "\n");
}
else
{
textBox3.AppendText(currentProxy + "\n");
}*/
//PingReply reply = proxy.Send(currentProxy.Split(':')[0], Convert.ToInt32(currentProxy.Split(':')[1]));
PingReply reply = await proxy.SendPingAsync("174.69.75.251", 5000);
if (reply.Status == IPStatus.Success)
{
textBox2.AppendText(currentProxy + "\n");
}
else if (reply.Status == IPStatus.TimedOut)
{
}
else if (reply.RoundtripTime >= 5000)
{
textBox3.AppendText(currentProxy + "\n");
}
else
{
textBox3.AppendText(currentProxy + "\n");
}
}
catch (PingException ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
}
That is everything including the loop and incremented integer to match the number of proxies in the string[] called proxyList.
What I want to do is see if the proxy is capable of working in a webBrowser control without the form/UI freezing.
A ping request can't test an applicative PORT. For this, you have telnet.
The parameters taken by 'ping.Send' are:
ping.Send('IP_ADDRESS', 'TIMEOUT');
Like it is said in the MSDN Documentation
You could specify a timeout using the overload of Ping.Send that accepts one. This takes the number of milliseconds to wait before timing out.
If you are in a UI application and this is causing your UI thread to freeze you could use the asynchronous method and await the result. This would allow your UI to remain responsive while the request is being sent.

C# Check if a Windows server is online [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Check if a server is available
I'm writing a program in C# that queries the Windows servers on our domain, one after another. Currently the program will hang waiting for a reply if a server is offline or has a fault, what is the best way to wait and if no response is received move on to the next server? I've never had to do this before so any help is much appreciated.
Thanks
Steve
It sounds as though you want to take a look at BackgroundWorker and threading (the Thread class). I imagine you're blocking the UI thread by making whatever call it may be to check on your servers.
By using threading you can report back to the user exactly what is going on and apply your own timeouts if need be.
You may ping your servers using PingReplay Class in C#:
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
namespace PingTest
{
public class PingExample
{
// args[0] can be an IPaddress or host name.
public static void Main (string[] args)
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes (data);
int timeout = 120;
PingReply reply = pingSender.Send (args[0], timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine ("Address: {0}", reply.Address.ToString ());
Console.WriteLine ("RoundTrip time: {0}", reply.RoundtripTime);
Console.WriteLine ("Time to live: {0}", reply.Options.Ttl);
Console.WriteLine ("Don't fragment: {0}", reply.Options.DontFragment);
Console.WriteLine ("Buffer size: {0}", reply.Buffer.Length);
}
}
}
}
The code has been adopted from MSDN, see here.

Categories