由于这个答案,我能够确定服务器是否正在侦听给定端口:
How to configure socket connect timeout
现在我正在尝试创建一个无限循环,它将被加载到form_load事件上,并将不断检查服务器是否在监听。
这是我的代码:
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();
}
}
答案 0 :(得分:2)
您可以在表单中添加Timer对象。在表单加载上启动计时器,并在计时器 Tick
事件中,运行您在无限循环中的代码。
注意:不要包含 while(true)
循环,只包括循环内的代码。你真的不希望你的GUI线程中出现无限循环:)
EDIT
我仍然认为您可能需要考虑重新设计应用程序行为,但这应该比我之前建议的计时器更好
更好的方法(应该处理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,但任何一个都应该让您启动并运行。
答案 1 :(得分:1)
如果在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();
答案 2 :(得分:0)
没有足够的代码来告诉我们需要知道的一切,但这是一个开始。
这个循环是在另一个线程上运行,还是只是在button_click事件中?
如果它没有在另一个线程上运行,可能你会点击该按钮,应用程序将显示为冻结,并且UI永远不会更新......你需要将其设置为运行在不同的主题。
如果它在另一个线程上运行,您可能需要使用InvokeRequired来更新表单上的标签。
This article显示了在不同线程上运行代码并正确使用InvokeRequired的代码。
答案 3 :(得分:0)
我认为你不能多次实例化一个对象。你可能需要把
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
在while循环之前
为了更好地诊断您的问题,您还可以使用
Console.WriteLine("Can't use");
Console.WriteLine("Start action");
查看是否存在线程问题(gui没有更新)
答案 4 :(得分:0)
关闭TCP连接需要一些时间。每次连接到远程服务器并在套接字上调用close时,都会发生TCP握手。
请参阅本指南http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm
避免以如此高的速率(半秒)打开/关闭插座。您可以在处于严密等待状态的远程服务器上构建一长串TCP连接,如果这不是您的服务器,则可以将其视为攻击。
对于失败的连接,这不是一个真正的问题。