Determine when a remote system is rebooted - c#

I am writing a c# program that calls a batch file that reboots the a remote system to another partition. Is there a way to know when the system is done rebooting? I would like to know when I can access the remote system once it is rebooted.

I would ping it to determine when it's back online. There's a Ping built right into .net.

When system A tells system B to reboot, maybe it could supply its ip address (or other contact info), and then in system Bs startup process it could read the file with the contact info and call back to system A.

You have a few options...
You can try to connect to a network service on the other system, ie: use Ping as suggested by Jon B.
However, if the system is one under your control, you have other options. You could setup a scheduled task (or install a service) to start on boot, and have the other system notify you when it is online. This would prevent you from needing to ping repeatedly.

I wish I had used this site before I spent all day Saturday trying to figure this out. Thanks for the help!! Below is what I ended up doing. This code will ping a computer and determine when it is back online. The next step will be to determine if I can open a network connection to the remote desktop port as suggested earlier. Feel free to make any comments on the code.
Note: Here are the added using statements:
using System.Net; // added
using System.Net.NetworkInformation;// added
using System.ComponentModel; // added
using System.Threading; // added
static void Main(string[] args)
{
string systemName = "172.30.11.148"; // Name of system beign pinged. System name used instead of ip due to DHCP
Ping pingSender = new Ping(); // Creates new ping object.
string data = "datadatadatadatadatadatadatadata"; // buffer of 32 bytes of data to transmit.
byte[] buffer = Encoding.ASCII.GetBytes(data); // buffer containing data.
int pingTimeout = 120; // Timeout in ms sent into pingSender.
int maxWaitTimeout = 60; // Maximum time to wait for system to reboot.
int counter = 1; // Used in while statement
bool connectStatus = false; // State of system connection.
Console.WriteLine("Wait for reboot to start before trying to establish connection.");
//Thread.Sleep(30000); // Waits 30 seconds at start of reboot to allow network to close.
Thread.Sleep(1000);
try
{
// Performs a ping on the system. If the system is available, while loop is exited and program
// continues. If the system is not available, program waits approximately 1 second and then
// pings the system again.
while (counter < maxWaitTimeout)
{
// Pings the system with 32 byts of data and waits for timeout
Console.WriteLine("Connection attempt #: " + counter + " of " + maxWaitTimeout);
PingReply reply = pingSender.Send(systemName, pingTimeout, buffer);
Console.WriteLine("Status of ping to: {0} - {1}", systemName, reply.Status);
if (reply.Status.ToString() == "Success")
{
connectStatus = true;
Console.WriteLine("\nRoundTrip time: {0}", reply.RoundtripTime);
Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
break;
}
Thread.Sleep(880);
counter += 1;
} // end while loop
if (connectStatus == true)
{
Console.WriteLine("\nAble to establish connection to: {0}", systemName);
}
else
{
Console.WriteLine("\nUnable to establish network connection using ping to: {0}", systemName);
}
} // end try
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
Console.ReadLine(); // Pause console
} // end main

Related

Using ping in a foreach loop in C#

I have an assignment in C# involving automation. My code is mainly based off things I have found online. My current problem is I am trying to read in IP addresses line by line from a CSV file into an array, pinging each object of the array, and appending the object so that each object will read "IP, status(if the ping was successful), response time"
I am trying to use a foreach loop but am running into errors. I am on a Mac so it is using mono. Any help would be appreciated.
(Full assignment below if it helps explain anything)
Starting with a premade C# console application, your application will upon running allow for three commands – start, stop, and exit. The application will, upon first running, ask the user for a CSV file (the user must provide a CSV file). This file will contain web addresses (1 per line) – the professor will supply the initial file.
Your application will be setup with a timer so that every time the timer runs, it pings the provided web addresses, gathering whether the server responds or not and the response time of each server. The timer should run continuously from the point the user types “start” until they type “stop” or “exit”. The data will be recorded back to another CSV file, containing the web address, response time, and whether or not the server responded at all.
using System;
using System.Timers;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Collections.Generic;
using Microsoft.VisualBasic;
namespace MT_proj4
{
public class Program
{
public static String[] addressArray = File.ReadAllLines("Project04_URLs.csv");
public static string IP;
public bool status;
public string time;
public static void Main()
{
foreach (string s in addressArray)
{
IP = Console.ReadLine();
bool PingHost(string)
{
bool pingable = false;
#pragma warning disable XS0001 // Find APIs marked as TODO in Mono
Ping pinger = new Ping();
#pragma warning restore XS0001 // Find APIs marked as TODO in Mono
try
{
PingReply reply = pinger.Send(IP);
pingable = reply.Status == IPStatus.Success;
}
catch (PingException)
{
return false;
}
for (int i = 0; i < addressArray.Length; i++)
{
addressArray[i] = addressArray[i] + pingable;
}
}
}
}
static void TimerClass()
{
Timer timer = new Timer(5000);
timer.Elapsed += HandleTimer;
timer.Start();
Console.WriteLine("Type 'exit' to close...");
Console.WriteLine("Enter a command...");
while (true)
{
Console.Write("Command: ");
string command = Console.ReadLine();
Console.WriteLine("Command entered: " + command);
if (command.ToLower() == "stop")
timer.Stop();
else if (command.ToLower() == "exit")
break;
}
}
static void HandleTimer(Object source, ElapsedEventArgs e)
{
Console.WriteLine("\nHandler not implemented...");
}
}
I would restructure your solution a bit. The ping code should run its own thread. Remove the timer, and simply block on Console.ReadLine(). If the results are not expected, repeat until you get either stop or exit.
The reason is the ping work and the console processing are on the same thread. These will block.
Try this:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("pinging....until stop command");
Thread pinger = new Thread(DoPinging);
pinger.Start();
while (true)
{
string command = Console.ReadLine();
if (command.ToLower() == "stop")
break;
else if (command.ToLower() == "exit")
break;
Console.WriteLine("Ignoring-> " + command);
}
pinger.Abort();
}
static void DoPinging()
{
// here goes the pinging code
}
}
In your example code, it looks like you want to read input for ping from Console as well, after the line read, if the value doesn't equal the stop commands (stop, exit), put the value into a queue and let the ping code read from the queue.
You mention reading a CSV file for the addresses to ping (but your example code doesn't reference a file). You can take this as a command line argument (string[] passed in main) and do the work for processing the file in the DoPinging method.
If you want me to add more detail to that, please comment below and I will work on that.
Thnx
Matt

Is a named pipe able to do what i want to do?

This is take II, i posted the other week and my question was put on hold, i adjusted my text but could not get a review, and the system closed the original post.
Logic
Server Side: Read only - Server Opens pipe then at regular interval checks if there is content (i.e. not at end of stream) and reads info. This check has to be poll based as only during the poll is there a valid context to pass on the data..
Client Side: Write-only - Open pipe, write to pipe, close (client.exe called many times, has short life span, code below is test code), e.g. some other script will "call client.exe with info"
Can this work flow be handled in pipes ? e.g. snippet of client code shown only the first client message is seen by the "server"
If pipes can do this after coding tips as most examples are for client - servers having similar life cycles.
Code snippets
for (int i = 0; i < 10; i++)
{
//Client - simulate exe starting and ending
var client = new NamedPipeClientStream(".", "PipesOfPiece", PipeDirection.Out, PipeOptions.WriteThrough);
client.Connect();
StreamWriter writer = new StreamWriter(client);
Console.WriteLine("Client about to send message");
writer.WriteLine("Called from client i = {0}", i);
writer.Close();
client.Close();
Thread.Sleep(5000);
}
// server snippet
var server = new NamedPipeServerStream("PipesOfPiece", PipeDirection.In);
server.WaitForConnection(); <= can this we optional with code below
StreamReader reader = new StreamReader(server);
while (true)
{
// simulate start of poll code
if (server.IsConnected)
{
if (!reader.EndOfStream)
{
var line = reader.ReadToEnd();
Console.WriteLine("Server: {0}", line);
}
} // End of poll code
Thread.Sleep(1000);
}
// server snippet
var server = new NamedPipeServerStream("PipesOfPiece", PipeDirection.In);
server.WaitForConnection(); <= can this we optional with code below
StreamReader reader = new StreamReader(server);
while (true)
{
// simulate start of poll code
if (server.IsConnected)
{
if (!reader.EndOfStream)
{
var line = reader.ReadToEnd();
Console.WriteLine("Server: {0}", line);
}
} // End of poll code
Thread.Sleep(1000);
}
So I am rusty on my pipes, I am hoping that a pipe can be opened, written to then read, and the waitforconnect() is there for the cases where you want this and is optional. I suppose it all triggers around who owns the pipe, i.e. if the server opens a pipe and is waiting for someone to write for it, why does it need to wait for a connect ? (I am hoping the server is the owner so when it ends, the pipe disappears)
Without a good, minimal, complete code example that reliably reproduces whatever specific problem you are having, it is impossible to provide specific advice as to how to fix that problem. However, I can at least try to answer some of your questions about how named pipes can be used, and provide a code example to illustrate some of the concepts.
First, some rules and observations:
A pipe instance can be used for only one connection. Note that pipes inherit Stream, and streams have a very specific paradigm: you open one, read to the end, and then you're done with the stream. Some streams, like FileStream, are seekable but even there you are only ever dealing with a single resource (i.e. the original file…you can't reconnect a FileStream to a different file), and network streams aren't even seekable.
A pipe must be connected before you perform I/O on it.
You may have multiple instances of pipes with the same name (if you initialize them correctly…by default, you may only have one pipe of any given name).
Clients trying to connect to a named pipe will wait until such a pipe exists. It does not need to exist at the time the client initiates the connection.
Only one client can connect to any given instance of a pipe. Any given instance of a server pipe can only ever handle a single client during its entire lifetime (see the very first point above).
So, what about your questions?
Can this work flow be handled in pipes ?
If I understand the work-flow correctly, yes. But you need to be careful to implement it correctly.
As I understand it, you want for your server to only attempt to read from clients periodically. At the same time, you want for a client to be able to write to a pipe at any time. This can be done, but it won't be straightforward.
Note per the above that you cannot open a single server pipe, and then let multiple clients periodically connect and disconnect from that pipe. Once the first client has connected, the pipe is no longer usable. It's a stream, and that first client's disconnection causes the stream to reach its end. It's done.
Note also that while a client can attempt to connect to a pipe that doesn't exist yet, it will wait until it can. So if you want your clients to not have to wait until the polling interval has expired, you'll need to maintain a server pipe available to connect to at all times.
But you've already said that you won't be able to handle data read from the server pipe at arbitrary points in time, but rather only during your polling interval.
Because pipes don't inherently support this specific scenario, IMHO the right way to implement it is to separate the behaviors into two different components. Maintain a simple pipe server that opens a pipe, waits for a client to connect, reads whatever the client has sent, closes the pipe, and then starts over.
Then have an intermediary class that can act as the go-between for the server I/O and whatever component you have that ultimately receives the data. This intermediary will retain a copy of the data after it's been received (the pipe code will deliver it to the intermediary as soon as it's received, regardless of the polling interval); the data will then later be retrieved by the polling component on its next polling interval (i.e. when the "context" as you put it is in fact available to which to deliver the data).
I am hoping that a pipe can be opened, written to then read, and the waitforconnect() is there for the cases where you want this and is optional
Unfortunately, your hope doesn't match the reality. Pipes can be bidirectional; i.e. "written to then read". But WaitForConnect() is not optional. The server must wait for a connection before attempting to read from the pipe, and for that pipe instance it will only ever be able to receive data from a single client.
I am hoping the server is the owner so when it ends, the pipe disappears
The server process is the one that actually creates the pipe. So yes, in that sense it is the owner. And yes, when the server process is terminated, any pipes it's created are destroyed.
Below, please find a simple code example that illustrates the use of multiple and concurrent servers and clients. You can adjust the numbers of each with the declared constants at the top of the example.
When running it, note that if more clients are active than servers, the additional clients will simply wait until a server pipe is available to connect to. Once one is, they will connect and proceed normally. If there are at least as many server pipe instances as there are clients trying to connect, all of the clients are serviced concurrently.
// NOTE: as a sample program, contrary to normal and correct
// programming practices error-handling has been omitted, and
// non-awaited async methods have been declared as void.
class Program
{
private const string _kserverName = "TestSO33093954NamedPipeClients";
private const int _kmaxServerCount = 3;
private const int _kmaxClientCount = 3;
static void Main(string[] args)
{
StartServers(_kmaxServerCount);
StartClients(_kmaxClientCount);
Console.WriteLine("Clients are being started. Press return to exit program.");
Console.ReadLine();
}
private static async void StartClients(int clientCount)
{
for (int i = 0; i < clientCount; i++)
{
RunClient(i);
await Task.Delay(300);
}
}
private static async void RunClient(int instance)
{
NamedPipeClientStream client = new NamedPipeClientStream(
".", _kserverName, PipeDirection.InOut, PipeOptions.Asynchronous);
client.Connect();
ReadClient(client);
using (StreamWriter writer = new StreamWriter(client))
{
writer.AutoFlush = true;
for (int i = 0; i < 5; i++)
{
string text =
string.Format("Instance #{0}, iteration #{1}", instance, i);
Console.WriteLine("Client send: " + text);
await writer.WriteLineAsync(text);
await Task.Delay(1000);
}
client.WaitForPipeDrain();
}
}
private static async void ReadClient(Stream stream)
{
using (TextReader reader = new StreamReader(stream))
{
string line;
while ((line = await reader.ReadLineAsync()) != null)
{
Console.WriteLine("Client recv: " + line);
}
}
}
private static void StartServers(int maxServerInstances)
{
for (int i = 0; i < maxServerInstances; i++)
{
RunServer(maxServerInstances);
}
}
private static async void RunServer(int maxServerInstances)
{
while (true)
{
using (NamedPipeServerStream server = new NamedPipeServerStream(
_kserverName, PipeDirection.InOut, maxServerInstances,
PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
{
await server.WaitForConnectionAsync();
byte[] buffer = new byte[1024];
int bytesRead;
Decoder decoder = Encoding.UTF8.GetDecoder();
while ((bytesRead =
await server.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
int cch = decoder.GetCharCount(buffer, 0, bytesRead);
char[] rgch = new char[cch];
decoder.GetChars(buffer, 0, bytesRead, rgch, 0);
Console.Write("Server recv: " + new string(rgch));
await server.WriteAsync(buffer, 0, bytesRead);
}
}
}
}
}
static class PipeExtensions
{
// As I am not running with .NET 4.6 yet, I need this little helper extension
// to wrap the APM-based asynchronous connection-waiting with the await-friendly
// Task-based syntax. Anyone using .NET 4.6 will have this in the framework already
public static Task WaitForConnectionAsync(this NamedPipeServerStream server)
{
return Task.Factory.FromAsync(
server.BeginWaitForConnection, server.EndWaitForConnection, null);
}
}

zeromq receive times out with EGAIN exactly the 255th time

library: clrzmq4 (https://github.com/zeromq/clrzmq4) in a c# project.
I am using zmq router-dealer configuration. The server is written in python and runs on linux. My dealer client written in c# runs on a windows machine. It sends messages and waits from the response
public Boolean sendMessage(Dictionary<String, String> msgDict)
{
ZError err;
String errStr;
var reqFrame = new ZFrame(JsonConvert.SerializeObject(msgDict));
retval = socket.Send(reqFrame, out err);
if (err != null)
{
errStr = String.Format("Error while sending command {3} {0} {1}", err.Text, err.Number, err.Name);
return false;
}
err = null;
respFrame = socket.ReceiveFrame(out err);
if (err != null)
{
errStr = String.Format("Error while receiving response data {0} {1} {2} {3}", err.Text, err.Number, err.Name, num_messages);
return false;
}
return true;
}
I set the sendTimeout and receiveTimeout on the socket to 2 min each.
When I keep calling sendMessage, exactly at the 255th time, receiveFrame timesout . On the server I see the message being processed and response being sent like everytime. And after this point, my send also timesout with the same error "EAGAIN" Resource temporarily unavailable.
There are the things I tried
Data with different lengths from 2 KB to 20 MB
set the sendhighwatermark and receivehighwatermark to different values: 10, 1000, 10000
Tried polling on the socket instead of ReceiveFrame
Tried making the sockets completely blocking.
In each of the above cases the failure occured at exactly the 255th time. In case of blocking sockets, it got blocked at the 255th time too.
I can't use netmq as much as I would like to because it doesn't have curvezmq and the server needs it.
I also tried a dealer client from another linux machine and it had no issues 255th time or even later.

what is the best multi-threading technique in c#

I'm developing an application that is running a lot of TcpListener tasks
using c# with .net 3.5 on windows server 2008
the TcpListener task is:
listening
to get an xml message
read an ID
from it
send a command to a
specific camera based on the ID to
take a snapshot and store it in a
folder
This is meant to execute within 1 second so I can take a snapshot with the camera. I've got a delay in executing this task, using the following code:
private Thread listen_thread;
public void start_listen()
{
this.listen_thread = new Thread(new ThreadStart(save_data));
this.listen_thread.Priority = ThreadPriority.Normal;
this.listen_thread.Start();
}
private void save_data()
{
//work to be done
}
Is this the best multi-threading technique to use? This application is running on a on dell poweredge 2900
with 2 quad core prosessor, and I think it could go faster. How might I be able to improve the latency of this code?
thats the code for the tcplistener
Int32 port = controller_port;
try
{
//this server ip
IPAddress localAddr = IPAddress.Parse(this_ip);
server = new TcpListener(localAddr, port);
server.Start();
Byte[] bytes = new Byte[256];
String data = null;
while (true)
{
Console.Write("Waiting for a connection... ");
TcpClient client = server.AcceptTcpClient();
Console.Write("Connected!");
data = null;
NetworkStream stream = client.GetStream();
int i;
string add_data = "";
Console.Write("Waiting...!");
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
try
{
string full_row = "";
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.Write("Received from controller: " + data);
add_data += data;
}
catch{}
}
}
}
then i divide it to get the ID .
It's not clear at all
how you receive requests
upon what you parallelize the application
It seems that you listen on different sockets and assign a thread on each of them.
I think this is a poor choice, because you can't control the parallelism degree.
You could instead have just one thread that nondeterministically listens on all sockets and assigns the connection to a thread pool, configured to simultaneously run at most n threads, where n is the parallelism degree of your machine (if you have a dual quadcore, n is equal to 8).
These methods have strikingly wrong names. start_listen() doesn't start listening. save_data() cannot possibly save any data until at least a connection is established. Which requires the client code to start up first and make the connection. Sure, one second is quickly gone with that. Starting a thread doesn't take more than a fraction of a millisecond when there's a core available.
Focus on the code that's missing in your snippet.

How to make SqlConnection timeout more quickly

I am using an SQL connection string with SqlClient.SqlConnection and specifying Connection Timeout=5 in the string, but it still waits 30 seconds before returning failure. How do I make it give up and return faster? I'm on a fast local network and don't want to wait 30 seconds. The servers that are not turned on take 30 seconds to fail. This is just a quick utility program that's going to always run just on this local network.
Edit: Sorry if I was unclear. I want the SqlConnection.Open to fail more quickly. Hopefully that could be deduced from the fact that the servers I want to fail more quickly are turned off.
Edit: It seems that the setting only fails sometimes. Like it knows the IP address of the server, and is using TCP/IP to talk to it (not local) but can't contact SQL Server at that address? I'm not sure what the pattern is, but I don't see the problem when connecting locally with SQL Server stopped, and I don't see it when attempting to connect to a non-existent server. I have seen it when attempting to contact a server where the Windows 2008 firewall is blocking SQL Server, though.
It looks like all the cases that were causing long delays could be resolved much more quickly by attempting a direct socket connection like this:
foreach (string svrName in args)
{
try
{
System.Net.Sockets.TcpClient tcp = new System.Net.Sockets.TcpClient(svrName, 1433);
if (tcp.Connected)
Console.WriteLine("Opened connection to {0}", svrName);
else
Console.WriteLine("{0} not connected", svrName);
tcp.Close();
}
catch (Exception ex)
{
Console.WriteLine("Error connecting to {0}: {1}", svrName, ex.Message);
}
}
I'm going to use this code to check if the server responds on the SQL Server port, and only attempt to open a connection if it does. I thought (based on others' experience) that there would be a 30 second delay even at this level, but I get a message that the machine "actively refused the connection" on these right away.
Edit: And if the machine doesn't exist, it tells me that right away too. No 30-second delays that I can find.
Edit: Machines that were on the network but are not turned off still take 30 seconds to fail I guess. The firewalled machines fail faster, though.
Edit: Here's the updated code. I feel like it's cleaner to close a socket than abort a thread:
static void TestConn(string server)
{
try
{
using (System.Net.Sockets.TcpClient tcpSocket = new System.Net.Sockets.TcpClient())
{
IAsyncResult async = tcpSocket.BeginConnect(server, 1433, ConnectCallback, null);
DateTime startTime = DateTime.Now;
do
{
System.Threading.Thread.Sleep(500);
if (async.IsCompleted) break;
} while (DateTime.Now.Subtract(startTime).TotalSeconds < 5);
if (async.IsCompleted)
{
tcpSocket.EndConnect(async);
Console.WriteLine("Connection succeeded");
}
tcpSocket.Close();
if (!async.IsCompleted)
{
Console.WriteLine("Server did not respond");
return;
}
}
}
catch(System.Net.Sockets.SocketException ex)
{
Console.WriteLine(ex.Message);
}
}
Update 2
I suggest rolling your own timeout. Something like this:
internal static class Program
{
private static void Main(string[] args)
{
Console.WriteLine(SqlServerIsRunning("Server=foobar; Database=tempdb; Integrated Security=true", 5));
Console.WriteLine(SqlServerIsRunning("Server=localhost; Database=tempdb; Integrated Security=true", 5));
}
private static bool SqlServerIsRunning(string baseConnectionString, int timeoutInSeconds)
{
bool result;
using (SqlConnection sqlConnection = new SqlConnection(baseConnectionString + ";Connection Timeout=" + timeoutInSeconds))
{
Thread thread = new Thread(TryOpen);
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
thread.Start(new Tuple<SqlConnection, ManualResetEvent>(sqlConnection, manualResetEvent));
result = manualResetEvent.WaitOne(timeoutInSeconds*1000);
if (!result)
{
thread.Abort();
}
sqlConnection.Close();
}
return result;
}
private static void TryOpen(object input)
{
Tuple<SqlConnection, ManualResetEvent> parameters = (Tuple<SqlConnection, ManualResetEvent>)input;
try
{
parameters.Item1.Open();
parameters.Item1.Close();
parameters.Item2.Set();
}
catch
{
// Eat any exception, we're not interested in it
}
}
}
Update 1
I've just tested this on my own computer using this code:
internal static class Program
{
private static void Main(string[] args)
{
SqlConnection con = new SqlConnection("Server=localhost; Database=tempdb; Integrated Security=true;Connection Timeout=5");
Console.WriteLine("Attempting to open connection with {0} second timeout, starting at {1}.", con.ConnectionTimeout, DateTime.Now.ToLongTimeString());
try
{
con.Open();
Console.WriteLine("Successfully opened connection at {0}.", DateTime.Now.ToLongTimeString());
}
catch (SqlException)
{
Console.WriteLine("SqlException raised at {0}.", DateTime.Now.ToLongTimeString());
}
}
}
and it obeys the Connection Timeout value in the connection string. This was with .NET 4 against SQL Server 2008 R2. Admittedly, it's a localhost connection which may give different results but it means I can't replicate the problem.
I can only suggest trying a similar chunk of code in your network environment and seeing if you continue to see long timeouts.
Old (incorrect) answer
I incorrectly thought the ConnectionTimeout property was settable, but it isn't.
Try setting SqlConnection.ConnectionTimeout instead of using the connection string.
The Command Timeout and the Connection Timeout are two different things.
SqlConnection.ConnectionTimeout is "the time (in seconds) to wait for a connection to open. The default value is 15 seconds." Thats only used when you call SqlConnection.Open().
The SqlCommand.CommandTimeout does what you want to do.

Categories

Resources