最近在对项目中Socket通讯中的服务端代码进行优化,保证能接受尽可能多的客户端的连接,并且不会丢掉连接,不会掉数据包。经过一段时间的反复测试和修改,终于达到了这一要求。服务端代码采用了异步通讯的方式,并使用ManualResetEvent来对线程进行控制。在程序中,ManualResetEvent 的使用很关键。 ManualResetEvent 允许线程通过发信号互相通信。通常,此通信涉及一个线程在其他线程进行之前必须完成的任务。当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时,它调用 Reset 以将 ManualResetEvent 置于非终止状态,此线程可被视为控制 ManualResetEvent。调用 ManualResetEvent 上的 WaitOne 的线程将阻止,并等待信号。当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。一旦它被终止,ManualResetEvent 将保持终止状态(即对 WaitOne 的调用的线程将立即返回,并不阻塞),直到它被手动重置。可以通过将布尔值传递给构造函数来控制 ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则为 false。现在贴出主要的代码,欢迎大家指正,代码如下所示:
void ButtonStartListenClick(object sender, System.EventArgs e)
{
try
{
// Check the port value
if(textBoxPort.Text == "")
{
MessageBox.Show("Please enter a Port Number");
return;
}
if (txtConnectNum.Text.Trim() != "")
{
iConnectNum = int.Parse(txtConnectNum.Text.Trim());
Flage = 0;
}
else
{
MessageBox.Show("Please enter a Connect Number");
return;
}
string portStr = textBoxPort.Text;
int port = System.Convert.ToInt32(portStr);
// Create the listening socket...
m_mainSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint (IPAddress.Any, port);
// Bind to local IP Address...
m_mainSocket.Bind( ipLocal );
// Start listening...
m_mainSocket.Listen(10000);
// Set the event to nonsignaled state.设置无信号状态的事件
allDone.Reset();
// Create the call back for any client connections...
m_mainSocket.BeginAccept(new AsyncCallback (OnClientConnect), null);
// Wait until a connection is made before continuing.等待连接创建后继续
allDone.WaitOne();
UpdateControls(true);
}
catch(SocketException se)
{
MessageBox.Show ( se.Message );
}
}