不断检查服务器是否正在使用C#侦听给定端口
本文关键字:检查 服务器 是否 | 更新日期: 2023-09-27 18:28:46
由于这个答案,我能够确定服务器是否在侦听给定的端口:
如何配置套接字连接超时
现在我正试图创建一个无休止的循环,它将加载到formload事件中,并不断检查服务器是否在侦听。
这是我的代码:
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";}
如果我将以下代码放入"on_button_click"事件-一切都很好(除了-我每次都必须点击按钮才能刷新状态)
当我创建无休止的循环时,我根本没有得到任何结果:
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();
}
}
我想这与线程有关,但我就是想不通。可能是什么问题?
编辑:
计时器刻度解决方案:
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();
}
}
您可以将Timer对象添加到表单中。在表单加载时启动计时器,并在计时器
Tick
事件中运行您在无限循环中的代码。
注意:不要包含while(true)
循环,只包含循环中的代码。你真的不想在你的GUI线程中有一个无限循环:)
编辑
我仍然认为你可能需要考虑重新设计应用程序的行为,但这应该比我之前建议的计时器更好
Timer的一个更好的方法(应该解决UI滞后问题)是在UI中添加一个BackgroundWorker。添加类似于以下内容的DoWork
方法:
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;
}
注意:如果您使用的是.Net 4.0,您可能需要考虑使用任务工厂和取消令牌,而不是BackgroundWorker,但其中任何一个都应该让您启动并运行。
如果在GUI线程上执行该循环,它将阻塞GUI,因为它无法接收用户输入。
您必须在不同的线程上执行代码,然后使用Invoke
或BeginInvoke
更新UI。类似于:
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();
我不认为您可以多次实例化一个对象。您可能需要放置
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
在while循环之前
为了更好地诊断你的问题,你也可以使用
Console.WriteLine("Can't use");
Console.WriteLine("Start action");
查看是否存在线程问题(gui未更新)
没有足够的代码来告诉我们需要知道的一切,但这里是一个开始。
这个循环是在另一个线程上运行,还是只是在button_click事件中?
-
如果它没有在其他线程上运行,很可能你会单击按钮,应用程序将显示为冻结状态,并且UI永远不会更新。。。您需要将其设置为在其他线程上运行。
- 您可以在更新标签后立即抛出Application.DoEvents()命令来解冻UI并更新标签,但这在实时代码中是不可行的。您将希望在生产应用程序中为您的检查创建一个新线程。Application.DoEvents在这种情况下会给您带来问题
-
如果它在不同的线程上运行,您可能需要使用InvokeRequired来更新表单上的标签
本文展示了在不同线程上运行代码并正确使用InvokeRequired的代码。
关闭TCP连接需要时间。每次连接到远程服务器并在套接字上调用关闭时,都会发生TCP握手。
请参阅本指南http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm
避免以如此高的速率(半秒)打开/关闭插座。您可以在处于关闭等待状态的远程服务器上建立一长串TCP连接,如果这不是您的服务器,则可能被认为是一种攻击。
对于失败的连接,这并不是一个真正的问题。