Ping reply taking too long/not working - c#

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.

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.

blocking listen prevents disconnect

Overview of Problem:
I need to connect to an IRC Server. Once connected, the program will send a message to the channel, and a response will occur over multiple lines back. I need to read these lines and store in a variable for later use. A special character at the end of the message (]) will define the end of the message over multiple lines. Once we have received this character, the IRC session should disconnect and processing should continue.
Situation:
I am using the Smartirc4net library. Calling irc.Disconnect() takes about 40 seconds to disconnect the session. Once we've received the ] character, the session should be disconnected, Listen() should not be blocking, and the rest of the program should continue to run.
Research:
I have found this: smartirc4net listens forever, can't exit thread, and I think it might be the same issue, however, I am unsure of what I need to do to resolve the problem.
Code:
public class IrcCommunicator
{
public IrcClient irc = new IrcClient();
string data;
public string Data { get { return data; } }
// this method we will use to analyse queries (also known as private messages)
public void OnQueryMessage(object sender, IrcEventArgs e)
{
data += e.Data.Message;
if (e.Data.Message.Contains("]"))
{
irc.Disconnect(); //THIS TAKES 40 SECONDS!!!
}
}
public void RunCommand()
{
irc.OnQueryMessage += new IrcEventHandler(OnQueryMessage);
string[] serverlist;
serverlist = new string[] { "127.0.0.1" };
int port = 6667;
string channel = "#test";
try
{
irc.Connect(serverlist, port);
}
catch (ConnectionException e)
{
// something went wrong, the reason will be shown
System.Console.WriteLine("couldn't connect! Reason: " + e.Message);
}
try
{
// here we logon and register our nickname and so on
irc.Login("test", "test");
// join the channel
irc.RfcJoin(channel);
irc.SendMessage(SendType.Message, "test", "!query");
// here we tell the IRC API to go into a receive mode, all events
// will be triggered by _this_ thread (main thread in this case)
// Listen() blocks by default, you can also use ListenOnce() if you
// need that does one IRC operation and then returns, so you need then
// an own loop
irc.Listen();
// when Listen() returns our IRC session is over, to be sure we call
// disconnect manually
irc.Disconnect();
}
catch (Exception e)
{
// this should not happen by just in case we handle it nicely
System.Console.WriteLine("Error occurred! Message: " + e.Message);
System.Console.WriteLine("Exception: " + e.StackTrace);
}
}
}
IrcBot bot = new IrcBot();
bot.RunCommand();
ViewBag.IRC = bot.Data;
As you can see, once this
Thank you for your time to look at this code and read my problem description. If you have any thoughts, or other suggestions, please let me know.
Mike
I was able to successfully disconnect straight away by calling RfcQuit() within OnQueryMessage(), before irc.Disconnect();

DisconnectedContext was detected - Threadpool and Ping

I'm attempting to create a multi-threaded application which will allow me to ping thousands of hosts, the results of the ping are written to a richtextbox.
After this application executes, once it's iterated through a thousand or so addresses, I'm presented with the following exception:
DisconnectedContext was detected
Message: Transition into COM context 0x4410e0 for this RuntimeCallableWrapper failed with the following error: System call failed. (Exception from HRESULT: 0x80010100 (RPC_E_SYS_CALL_FAILED)). This is typically because the COM context 0x4410e0 where this RuntimeCallableWrapper was created has been disconnected or it is busy doing something else. Releasing the interfaces from the current COM context (COM context 0x440f70). This may cause corruption or data loss. To avoid this problem, please ensure that all COM contexts/apartments/threads stay alive and are available for context transition, until the application is completely done with the RuntimeCallableWrappers that represents COM components that live inside them.
I'm not entirely sure what's causing this, I at first figured it was due to my not disposing Ping but I've since addressed that and the problem still persists.
If anyone has any information on this it would be greatly appreciated.
Thank you all.
public static void LogTextEvent(RichTextBox TextEventLog, Color TextColor, string EventText)
{
if (TextEventLog.InvokeRequired)
{
TextEventLog.BeginInvoke(new Action(delegate { LogTextEvent(TextEventLog, TextColor, EventText); }));
return;
}
string nDateTime = DateTime.Now.ToString("hh:mm:ss tt") + " - ";
// color text.
TextEventLog.SelectionStart = TextEventLog.Text.Length;
TextEventLog.SelectionColor = TextColor;
// newline if first line, append if else.
if (TextEventLog.Lines.Length == 0)
{
TextEventLog.AppendText(nDateTime + EventText);
TextEventLog.ScrollToCaret();
TextEventLog.AppendText(Environment.NewLine);
}
else
{
TextEventLog.AppendText(nDateTime + EventText + Environment.NewLine);
TextEventLog.ScrollToCaret();
}
}
private void button1_Click(object sender, EventArgs e)
{
string[] logFile = File.ReadAllLines("addrs.txt");
var addresses = new List<string>(logFile);
foreach (string ip in addresses)
{
// See http://stackoverflow.com/questions/4744630/unexpected-behaviour-for-threadpool-queueuserworkitem
// for reason to use another variable in the loop
string loopIp = ip;
WaitCallback func = delegate
{
if (PingIP(loopIp))
{
LogTextEvent(richTextBox1, Color.Green, "[ " + loopIp.ToUpper() + " ] - Ping Success");
}
else
{
LogTextEvent(richTextBox1, Color.Red, "[ " + loopIp.ToUpper() + " ] - Ping FAIL!");
}
};
ThreadPool.QueueUserWorkItem(func);
}
}
public static bool PingIP(string IP)
{
bool result = false;
var ping = new Ping();
try
{
//var ping = new Ping();
PingReply pingReply = ping.Send(IP);
if (pingReply.Status == IPStatus.Success)
result = true;
}
catch
{
result = false;
}
finally
{
ping.Dispose();
}
return result;
}
AndyDing is mostly right... problem is with ScrollToCaret... this drove me mad...
I swapped
rtbox.Select(box.Text.Length, 0);
rtbox.ScrollToCaret();
with
rtbox.Focus();
rtbox.Select(rtbox.Text.Length, 0);
problem solved... In my situation swapping RichTextBox for TextBox was not possible... need different colors/alignment bla bla bla... but AndyDing got me on the right path.
Cheers
I encountered the similar "DisconnectedContext" failure, and spent one day to finally figure out the problem is induced by ScrollToCaret() of RichTextBox. I replaced it with a TextBox, which automatically scrolls down, so it even doesn't have a ScrollToCaret() method. Fortunately I don't really need those extra features provided by RichTextBox, a TextBox is just fine in my application. You can give a try.

Need help in "Socket Programming" using Visual C# (Dot Net Framework 4.0)?

Recently, I was given an assignment...
"To develop a Windows Forms application which can be installed on various windows machines at an office or enterprise. There would be a database in just one machine(ALPHA machine).. This database would be used by applications on other Beta machines to access data. The application would itself manage to check if it is an Alpha or a Beta (Has Database file with it?) and hence has to act as a server or a client."
I can do everything except the Network and Inter-Application Communication requirements. So, I started to learn Socket Programming over the Internet and I have gone through this link...
The idea I am working on is...
To have the client send the message to server.
To have the server accept this message and put this message in queue.
Read the message to get Client's IP Address and the its Request for Data.
Apply this request on database and get the result.
Convert the result in string.
Send it to the requesting client.
I can manage to perform steps 3,4 & 5. I am stuck on 1, 2 & 6.
Towards this...
I have created a function for Server as well as for client who return the Sockets when called. I create a separate function as I like my code to be clean, tidy and understandable after years.
Check my code below...
For Server...
private Socket GetServerReady()
{
IPEndPoint RemoteEP = new IPEndPoint(IPAddress.Any, 8000);
Socket newSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
newSock.Connect(RemoteEP);
newSock.Listen(10);
return (newSock);
}
You will notice there is no Accept() method anywhere, This is because I wish to call it like below for further use...
Socket CltSock = GetServerReady().Accept();
The Code for Client is...
private Socket GetClientReady()
{
IPEndPoint RemoteEP = new IPEndPoint(IPAddress.Parse(txtBxHost2.Text.Trim()), 8000);
Socket ServerSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ServerSock.Connect(RemoteEP);
return (ServerSock);
}
Finally, The questions are....
"Where is the appropriate place to call the functions I wrote above?"
"Should I call the Server and Client Function in Form_Load() Event?"
"What must be the next step towards my main intention which is point 1,2 & 6 mentioned above?"
I don't expect the full code that I can just copy as it is. Just the correct procedure and a little detail over the concept would do.
I would be using just a single PC for testing purpose. Also, another limitation is, It would all be coded in a single application. I don't want to write two separate applications for client & server.
I hope I made it all clear for you to understand.
Thanks a Lot.
Awaiting the response.
I was struggling to get things done and somehow managed to get the solution.
Below is my solution:
Server Side code:
(I put this code in a function which loops back the execution if any exception is caught)
private void Looper()
{
int i = 0;
int AttemptCount = 1;
while (i == 0)
{
try
{
TcpListener tL = new TcpListener(Network.GetLocalIPAddress(), 56009);
tL.Start(10);
Socket tS = tL.AcceptSocket();
if (tS.Connected)
{
NetworkStream nS = new NetworkStream(tS);
StreamReader Reader = new StreamReader(nS);
Output = Reader.ReadToEnd().Trim();
Reader.Close();
nS.Close();
tS.Close();
tL.Stop();
//If Done, End Execution
i = 1;
}
else
{
MessageBox.Show("The connection to the client is broken or failed..!!\n\nPlease check connection and try again.","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}
catch (SystemException ex)
{
//If Not, Loop Execution Again
if (MessageBox.Show("Exception: " + ex.Message + "\n\nAttempt Count: " + AttemptCount + "\n\nDo you want to terminate the transmission?", "Error", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.Yes)
{
i = 1;
ResetTimer.Stop();
}
else
{
i = 0;
AttemptCount++;
}
}
}
}
When above function is called, The server waits to accept any incoming socket. If there is any error somewhere due to port re-usage or anything, It loops back itself and resets the server. (So, we don't have to manually call the server function again & again.)
Once the server accepts any incoming socket, the execution ends up successfully. Lot's of time we don't want to keep invoking server even after a successful reception. So, I, instead of calling this function in a button "click_event", I called it in a timer Tick_Event. So, the human need is eliminated at server side.
This leads to a problem. Once the server starts waiting to accept, It is in blocking mode.
It hangs all the processes and controls in same thread. So, I moved the call to above function to BackgroundWorker's "Do_Work" Event.
Check below Code:
private void GetServerReady()
{
if (!bW.IsBusy)
{
bW.RunWorkerAsync();
txtBxHistory.Text += "\r\n" + Output;
}
}
private void bW_DoWork(object sender, DoWorkEventArgs e)
{
Looper();
}
private void ResetTimer_Tick(object sender, EventArgs e)
{
GetServerReady();
}
"bW" is "BackgroundWorker".
"Output" is a variable I defined globally.
The reason we need a variable is that,
BackgroundWorker has its own thread to execute the code placed in its "Do_Work" Event. So, a TextBox from our application's thread can't be used by BackgroundWorker to store the received output. Doing this to a variable and then setting TextBox's Text property to this variable does the trick.
Client Side code:
private void btnSend_Click(object sender, EventArgs e)
{
TcpClient socketForServer;
try
{
socketForServer = new TcpClient(txtBxDestIP.Text.Trim(), 56009);
}
catch
{
MessageBox.Show("Failed to connect to server at " + txtBxDestIP.Text.Trim() + ":999", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
NetworkStream networkStream = socketForServer.GetStream();
StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
try
{
string InputString;
InputString = Network.GetLocalIPAddress() + ": " + txtBxData.Text;
streamWriter.Write(InputString);
streamWriter.Flush();
socketForServer.Close();
txtBxHistory.Text += "\r\nMe: " + txtBxData.Text.Trim();
txtBxData.Clear();
}
catch
{
MessageBox.Show("Exception reading from Server.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
streamWriter.Close();
networkStream.Close();
socketForServer.Close();
}
"txtBxDestIP" is a TextBox having the Destination IP address as Text.
"txtBxData" is a TextBox having the text to be sent.
This code works flawless for me. With above solution I can achieve all my motives from step 1 to 6 (Mentioned in the question above.)
I hope it helps others too. Please suggest if there is a better and efficient way to perform this.
Thanks.
Regards.

C#: Timeout on SerialPort.Open?

I have an autodetect thread that tries to open the ports in order and match the received data, thus detecting the port where the relevant device sends the data. Now, there are some ports where the SerialPort.Open simply hangs the thread for ~30 secs. How can I set a timeout on the SerialPort.Open function?
From MSDN
Only one open connection can exist per SerialPort object.
The best practice for any application is to wait for some amount of time after calling the Close method before attempting to call the Open method, as the port may not be closed instantly.
When you call Close(), this worker thread needs time to spin down and exit. The amount of time needed is not specified and you can't verify that it was done. All you can do is wait at least one second before you call Open() again.
I encountered the same problem and I hope my solution can help you.
You can detect the Serial Ports in a separate thread, which will be aborted in 500 ms.
// the Serial Port detection routine
private void testSerialPort(object obj)
{
if (! (obj is string) )
return;
string spName = obj as string;
SerialPort sp = new SerialPort(spName);
try
{
sp.Open();
}
catch (Exception)
{
// users don't want to experience this
return;
}
if (sp.IsOpen)
{
if ( You can recieve the data you neeed)
{
isSerialPortValid = true;
}
}
sp.Close();
}
// validity of serial port
private bool isSerialPortValid;
// the callback function of button checks the serial ports
private void btCheck(object sender, RoutedEventArgs e)
{
foreach (string s in SerialPort.GetPortNames())
{
isSpValid = false;
Thread t = new Thread(new ParameterizedThreadStart(testSerialPort));
t.Start(s);
Thread.Sleep(500); // wait and trink a tee for 500 ms
t.Abort();
// check wether the port was successfully opened
if (isSpValid)
{
textBlock1.Text = "Serial Port " + s + " is OK !";
}
else
{
textBlock1.Text = "Serial Port " + s + " retards !";
}
}
}
}
Possible improvements could be added into the solution. You can use multi-Thread to accelerate the process and use ProgressBar to display the progress clearly.
Add this in your code:
commPort = new SerialPort();
commPort.ReadTimeout = 1000000;
commPort.WriteTimeout = 1000000;
And I suggest you to see SerialPort.Open Method
If I understood you correctly, you wish to read data from the serial port even after timeout occurred.
If so, then you should catch the TimeoutException and continue your loop. e.g. MSDN CODE
public static void Read()
{
while (_continue)
{
try
{
string message = _serialPort.ReadLine();
Console.WriteLine(message);
}
catch (TimeoutException) { }
}
}

Categories