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.
Related
I've created a simple client/server program which takes an input from the client and returns a answer to the input by looking in the text file to see if there is an answer associated with the input.
The issue I'm having is that I get the response on the server side but I don't know how to send it back to the client (it just returns the input on the client side).
The second issue is that it will execute once, as in, it will only take in one input. I tried adding a loop but couldn't get it to work.
Server.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace server
{
class server
{
const string SERVER_IP = "127.0.0.1";
static void Main(string[] args)
{
//Create Dictionary
Dictionary<string, string> dict = new Dictionary<string, string>();
//---Read Text File containing commands ---
StreamReader sr = new StreamReader(#"C:\Users\Desktop\potato.txt");
string line;
//Splits the text into commands:responses
while ((line = sr.ReadLine()) != null)
{
string[] arr = line.Split(';');
dict.Add(arr[0], arr[1]);
}
//Print dictionary TESTING FUNCTION
foreach (KeyValuePair<string, string> kvp in dict)
{
Console.WriteLine("Command = {0} Response = {1}", kvp.Key, kvp.Value);
}
//---Input the port number for clients to conect---
Console.Write("Input port" + System.Environment.NewLine);
int PORT_NO = int.Parse(Console.ReadLine());
//---listen at the specified IP and port no.---
IPAddress localAdd = IPAddress.Parse(SERVER_IP);
TcpListener listener = new TcpListener(localAdd, PORT_NO);
Console.WriteLine("Listening for Commands");
listener.Start();
//---incoming client connected---
TcpClient client = listener.AcceptTcpClient();
//---get the incoming data through a network stream---
NetworkStream nwStream = client.GetStream();
byte[] buffer = new byte[client.ReceiveBufferSize];
//---read incoming stream---
int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);
//---convert the command data received into a string---
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received Command : " + dataReceived);
//---Search Command and send a response
string Response;
if (dict.TryGetValue(dataReceived, out Response))
{
Console.WriteLine(Response);
}
//---write back the response to the client---
Console.WriteLine("Sending Response : " + Response);
nwStream.Write(buffer, 0, bytesRead);
Console.ReadLine();
}
}
}
You need to convert Response to a byte[] just as you do in the client sending your request (i.e. bytesToSend). E.g.:
Console.WriteLine("Sending Response : " + Response);
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(Response);
nwStream.Write(bytesToSend, 0, bytesToSend.Length);
Console.ReadLine();
That said, you have made the classic mistake every person does who tries to write TCP code without first reading references about TCP and sockets: you mistakenly believe that when you read from a socket, you will always receive in that single operation every byte that was read. So even with the above fix (which does address the issue on the server side), it is possible you will see partial responses on the client side (not as likely when testing locally, but much more likely if you move to running on the Internet or across LANs, and especially as the message size increases).
For low-volume network interaction, you may want to consider wrapping your NetworkStream with StreamReader and StreamWriter objects, and use ReadLine() and WriteLine() to receive and send data (i.e. use line-breaks as the delimiter for the data).
As for dealing with multiple requests, given the code you have presented here, the simplest approach is to add a loop around the server code after the listener.Start() method. I.e. containing all the code after that statement, starting with the call to listener.AcceptTcpClient() and going to the last statement in the method. However, again this is only appropriate for low-volume network code. If you anticipate clients will need your server to handle multiple requests and especially if in quick succession, what you really want is for the client to maintain the connection, i.e. only connect once and then have it send multiple requests on that same connection.
Similarly, if you want to be able to handle multiple clients at once, you cannot run the server in a single thread. Instead, at the very least you'll need to use the thread-blocking logic you're using now, where you have a new thread created for each client. Better, would be to use the non-blocking API (e.g. NetworkStream.BeginRead(), StreamReader.ReadLineAsync(), etc. … there are many asynchronous options to choose from), and let .NET deal with the threading for you.
Doing it that way will require significant changes to the server code. You really should look carefully at various samples on MSDN and Stack Overflow to see how this sort of thing is done. I also strongly recommend you read through the Winsock Programmer's FAQ. It is not specifically about .NET at all, but does cover all of the key details you'll need to know in order to effectively and correctly use the .NET API.
My issue is that after I connect to the IRC and I am receiving raw text from the IRC and logging it but then it just decides to disconnect from the server after inactivity or 2-3 seconds after I start it (unconfirmed).
Any help would be appreciated. Here's my code (had issues posting it here):
http://pastebin.com/Ls5rv0RP
I need it to stop disconnecting but I cant really find a way to. I know the popular mIRC client disconnects from Twitch after x amount of time but reconnects and that's fine to as long as it KNOWS to reconnect in a timely manner (2-5 seconds).
The part were it replys to PING/PONG's:
if (buf.StartsWith("PING ")) output.Write(buf.Replace("PING", "PONG") + "\r\n"); output.Flush();
Any help is appreciated.
This code below helps keep my Twitch bot from disconnecting by running a separate thread that pings to the IRC server.
PingSender Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace TwitchBot
{
/*
* Class that sends PING to irc server every 5 minutes
*/
class PingSender
{
static string PING = "PING ";
private Thread pingSender;
// Empty constructor makes instance of Thread
public PingSender()
{
pingSender = new Thread (new ThreadStart (this.Run) );
}
// Starts the thread
public void Start()
{
pingSender.Start();
}
// Send PING to irc server every 5 minutes
public void Run()
{
while (true)
{
Program.irc.sendIrcMessage(PING + "irc.twitch.tv");
Thread.Sleep(300000); // 5 minutes
}
}
}
}
Usage:
/* Ping to twitch server to prevent auto-disconnect */
PingSender ping = new PingSender();
ping.Start();
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.
Hi to all i am new here and i have heard a lot about this website that it really helps you out. Hope you will be able to help me out!.
I have a very simple program which its only aim is to read from a serial port and prints it on the console window in C# for 2000 times.
I am just turning a variable resistor on a micro-controller that's all
Here below is the code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
namespace Testing_serial_v3._0
{
class Program
{
static void Main(string[] args)
{
string buff;
SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
port.Open();
for (int i = 0; i < 2000; i++)
{
buff = port.ReadLine();
Console.WriteLine(buff);
//Console.ReadLine();
}
}
}
}
But there is a funny thing happening in this code. When the console readline is commented as shown in the code above the value from the port changes as i turn the knob of the variable resistor. So this means it is working good.
On the other hand if i make the readline happen so that after each value i have to press a key the port reads the current value and even though i change the knob and press enter again the value will remain the first as if it is not resetting at all?
Do you have to include any other command lines so that the port will reset?
Hope you understand my problem and any other questions you need to know please don't hesitate i really need this problem fixed ASAP.
Many thanks and regards
The data coming through the port is a stream - when you read, you are gradually consuming the stream. You are not seeing "the most recent value", you are seeing "the next value in the stream". When you add the read-line, you add a delay which means there is a large backlog of data. It isn't that "it stayed the same"... Simply that you haven't read to the end (and the more recent values) yet.
In many cases, it would be preferable to deal with the network IO via an async callback so that reading values from the stream is not tied into delays like human data entry. That may involve some knowledge of threading, though.
You could also use a Task to read it in a separate thread and observe it there, kind of what #Marc Gravel mentions. You just have to wait until the task is finished or press enter to cancel it manually. Just another example of offloading the task to another thread.
Here's an example:
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ReadStreamAsyncTask
{
internal class Program
{
private static CancellationToken _cancelTaskSignal;
private static byte[] _serialPortBytes;
private static MemoryStream _streamOfBytesFromPort;
private static CancellationTokenSource _cancelTaskSignalSource;
private static void Main()
{
_serialPortBytes = Encoding.ASCII.GetBytes("Mimic a bunch of bytes from the serial port");
_streamOfBytesFromPort = new MemoryStream(_serialPortBytes);
_streamOfBytesFromPort.Position = 0;
_cancelTaskSignalSource = new CancellationTokenSource();
_cancelTaskSignal = _cancelTaskSignalSource.Token; // Used to request cancel the task if needed.
var readFromSerialPort = Task.Factory.StartNew(ReadStream, _cancelTaskSignal);
readFromSerialPort.Wait(3000); // wait until task is complete(or errors) OR 3 seconds
Console.WriteLine("Press enter to cancel the task");
_cancelTaskSignalSource.Cancel();
Console.ReadLine();
}
private static void ReadStream()
{
// start your loop here to read from the port and print to console
Console.WriteLine("Port read task started");
int bytesToReadCount = Buffer.ByteLength(_serialPortBytes);
var localBuffer = new byte[bytesToReadCount];
int bytesRead = 0;
bool finishedReading = false;
try
{
while (!finishedReading)
{
_cancelTaskSignal.ThrowIfCancellationRequested();
bytesRead += _streamOfBytesFromPort.Read(localBuffer, 0, bytesToReadCount);
finishedReading = (bytesRead - bytesToReadCount == 0);
}
}
catch (TaskCanceledException)
{
Console.WriteLine("You cancelled the task");
}
Console.WriteLine(Encoding.ASCII.GetString(localBuffer));
Console.WriteLine("Done reading stream");
}
}
}
You are sending thousands of data from micro-controller to the serial port (with delay of 1ms for ex.), which makes the buffer of the serial port filled with same values! If you read it one by one by pressing enter key, you are reading the first received ones...
I think if you want to read your data in computer by "Enter" key, you should send the date from micro-controller by a push button! It means you set the value by resistor, press the push button, the micro sends "One Byte" to the computer. You press the enter on the computer and let your computer read just "One Byte" from the serial port!
Also some modification to your code:
static void Main(string[] args)
{
int buff; // string to int
SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
port.Open();
for (int i = 0; i < 2000; i++)
{
Console.ReadLine(); // wait for the Enter key
buff = port.ReadByte(); // read a byte
Console.WriteLine(buff);
}
}
I hope this will work for you! :)
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