Reputation: 5227
thanks to this answer I was able to determine if Server is listening on a given port or not:
How to configure socket connect timeout
now I'm trying to create an endless loop, which will be loaded on form_load event and will be constantly checking if server is listening.
here is my code:
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect("192.168.0.131", 1095, null, null);
bool success = result.AsyncWaitHandle.WaitOne(500, true);
if (!socket.Connected)
{label3.Text = "can't use"; socket.Close();}
else
{label3.Text = "start action";}
If I put following code into "on_button_click" event - everything works fine (except for - I have to click the button every single time I want to refresh status)
and when I create endless loop - I'm not getting any results at all:
while (true)
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect("192.168.0.131", 1095, null, null);
bool success = result.AsyncWaitHandle.WaitOne(500, true);
if (!socket.Connected)
{
label3.Text = "can't use";
socket.Close();
}
else
{
//success = true;
label3.Text = "start action";
socket.Close();
}
}
I guess it has something to do with threading but I just can't figure it out. What might be the problem?
Edit:
timer tick solution:
private void Form1_Load_1(object sender, EventArgs e)
{
System.Windows.Forms.Timer MyTimer = new System.Windows.Forms.Timer();
MyTimer.Interval = (200);
MyTimer.Tick += new EventHandler(MyTimer_Tick);
MyTimer.Start();
}
public void MyTimer_Tick(object sender, EventArgs e)
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect("192.168.0.131", 1095, null, null);
bool success = result.AsyncWaitHandle.WaitOne(500, true);
if (!socket.Connected)
{
label3.Text = "can't use";
socket.Close();
//throw new ApplicationException();
}
else
{
//success = true;
label3.Text = "start action";
socket.Close();
}
}
Upvotes: 1
Views: 2583
Reputation: 17428
You can add a Timer object to your form. Start the timer on the form load, and in the timer Tick
event, run your code that you have in the infinite loop.
Note: DO NOT include the while(true)
loop, just the code inside the loop. You really don't want an infinite loop in your GUI thread :)
EDIT
I still think you may need to consider a redesign of the app behavior, but this should be better than the Timer I suggested earlier
A somewhat better approach to the Timer (which should take care of the UI lag issue) would be for you to add a BackgroundWorker to your UI. Add a DoWork
method similar to this:
void DoWork(object sender, DoWorkEventArgs e)
{
while(!_bw.CancellationPending)
{
// Do your socket connection stuff
// you can either update some member variables and call
// the progresschanged method or you can use a BeginIvoke call
// to update the labels, you CANNOT update the labels in this method
if (!_bw.CancellationPending)
{
// Checking the cancel pending before sleeping so that we don't sleep
// while a cancel is pending. There are better ways to do this with
// event handles, but this should get you off and running.
Thread.Sleep(1000);
}
}
e.Cancel = true;
}
Note: If you were using .Net 4.0, you may want to consider using the task factory and a cancellation token rather than the BackgroundWorker, but either one should get you up and running.
Upvotes: 2
Reputation: 54771
It takes time for a TCP connection to be closed. Each time you connect to the remote server and call close on the socket a TCP handshaking takes place.
See this guide http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm
Avoid, opening/closing sockets at such a high rate (half a second). You could build a long list of TCP connections on the remote server that are in a close wait condition, and if this isn't your server then it could be thought of as an attack.
For failed connections, this isn't really a problem.
Upvotes: 0
Reputation: 73564
There's not enough code to tell everything we need to know, but here's a start.
Is this loop running on a different thread, or is it just there in the button_click event?
If it's not running on a different thread, likely you'll click the button and the app will appear to freeze, and the UI will never get updated... You need to set this up to run on a different thread.
If it IS running on a different thread, you probably need to use InvokeRequired to update the labels on the form.
This article shows code for running code on a different thread and using InvokeRequired properly.
Upvotes: 0
Reputation: 412
I don't think you can instantiate an object more than once. You may need to put
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
before the while loop
To better diagnose your problem you could also use
Console.WriteLine("Can't use");
Console.WriteLine("Start action");
to see if there is a threading issue or not (with the gui not updating)
Upvotes: 0
Reputation: 62439
If that loop is executed on the GUI thread it will block the GUI because it becomes unable to receive user input.
You have to execute the code on a different thread and then update the UI using Invoke
or BeginInvoke
. Something like:
Thread t = new Thread(
o =>
{
while (true)
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect("192.168.0.131", 1095, null, null);
bool success = result.AsyncWaitHandle.WaitOne(500, true);
if (!socket.Connected)
{
label3.BeginInvoke((Action)(() => { label3.Text = "can't use"; }));
socket.Close();
}
else
{
//success = true;
label3.BeginInvoke((Action)(() => { label3.Text = "start action"; }));
socket.Close();
}
}
});
t.Start();
Upvotes: 1