本人已经用C#实现了多个客户端连接服务端的问题,但我还想限制客户端的连接数。例如我希望同时连接到服务端的数目为2,若第三个发起连接请求时会失败。
本人已基本想出解决限制客户端的连接数的方法,但是出现一个问题就是明明我是设置只允许连接N个,却可以连接N+1个,但第N+2个时就会失败,我没查出原因。
我的代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace TCPSERVER
{
public partial class FrmServer : Form
{
private Socket m_ServerListener = null;
private ClientInformationCls[] m_clientList;
delegate void SetTextCallback(string strText);
private const int MAX_CLIENT = 1; //client connnecting max number public FrmServer()
{
InitializeComponent();
} private static IPAddress GetServerIP()
{ IPHostEntry ieh = Dns.GetHostEntry(Dns.GetHostName()); return ieh.AddressList[0]; } private void BeginListen()
{
int intPort =8000; m_clientList=new ClientInformationCls[ MAX_CLIENT ]; IPAddress ServerIp = GetServerIP(); IPEndPoint iep = new IPEndPoint(ServerIp, intPort);
m_ServerListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_ServerListener.Bind(iep);
m_ServerListener.Listen(1);
} private void btnBeginListen_Click(object sender, EventArgs e)
{
try
{
BeginListen();
lstServerStatus.Items.Add("Server is starting listening...."); InitClientList(); Thread acceptThread = new Thread(new ThreadStart(AcceptClientThread));
acceptThread.Start();
}
catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
} private void AcceptClientThread()
{
int intClientIndex; Thread.CurrentThread.IsBackground = true; try
{
while (true)
{
intClientIndex = GetFreeClient();
if (intClientIndex != -1)
{
m_clientList[intClientIndex].IsIdle = false;
Socket clientSocket = m_ServerListener.Accept();
IPEndPoint remoEP = (IPEndPoint)clientSocket.RemoteEndPoint;
m_clientList[intClientIndex].ClientIP = remoEP.Address.ToString();
m_clientList[intClientIndex].ClientSocket = clientSocket;
SetText("connecting from " + m_clientList[intClientIndex].ClientIP); Thread DealingThread = new Thread(new ParameterizedThreadStart(RcvSndThread)); DealingThread.Start(m_clientList[intClientIndex]); }
}
} catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
} } private void RcvSndThread(object obj)
{
Thread.CurrentThread.IsBackground = true;
ClientInformationCls clientTmp = (ClientInformationCls)obj;
byte[] buffer = new byte[1024];
int intRcvCount; try
{
while (clientTmp.ClientSocket.Connected == true)
{
intRcvCount = clientTmp.ClientSocket.Receive(buffer);
SetText(Encoding.Default.GetString(buffer, 0, intRcvCount)); }
} catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
} catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
} private void InitClientList()
{
int i = 0;
for (i=0; i <= m_clientList.Length-1; i++)
{
m_clientList[i] = new ClientInformationCls();
m_clientList[i].ClientHostName="";
m_clientList[i].ClientIP = "";
m_clientList[i].Index=i;
m_clientList[i].IsIdle = true;
m_clientList[i].ClientSocket = null;
}
} private int GetFreeClient()
{
int i = 0;
for (i = 0; i <= m_clientList.Length - 1; i++)
{
if (m_clientList[i] == null) return -1;
if (m_clientList[i].IsIdle == true)
{
return i;
}
}
return -1;
} private void SetText(string strText)
{
if (this.lstServerStatus.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { strText });
}
else
{
this.lstServerStatus.Items.Add(strText);
}
} }
}
其中 ClientInformationCls是本人自定义的类,一个保存客户端SOCKET的连接信息,其中有个IsIdle属性用来记录该SOCKET是否可用
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
namespace TCPSERVER
{
class ClientInformationCls
{
private int m_intClientIndex; //client's index
private string m_strClientIP;
private string m_strClientHostName;
private bool m_blnIsIdle;
private Socket m_clientSocket;
public int Index
{
get{return m_intClientIndex;}
set{m_intClientIndex=value;}
} public string ClientIP
{
get { return m_strClientIP; }
set { m_strClientIP = value; }
} public string ClientHostName
{
get { return m_strClientHostName; }
set { m_strClientHostName = value; }
} public bool IsIdle
{
get { return m_blnIsIdle; }
set { m_blnIsIdle = value; }
}
public Socket ClientSocket
{
get { return m_clientSocket; }
set { m_clientSocket = value; }
}
}
} 我在AcceptClientThread函数中调用了
intClientIndex = GetFreeClient();
如果intClientIndex=-1的话表示不能在允许其他的客户端连接,这样就不会创建新的线程了,
现在我的问题是我明明创建了数组 m_clientList=new ClientInformationCls[ MAX_CLIENT ];
而MAX_CLIENT初始化时已经设置为1了,也就是说服务端最大的连接数为MAX_CLIENT=1,
而我测试的时候,服务端最大的连接数为MAX_CLIENT+1了,请高手帮忙看看
本人已基本想出解决限制客户端的连接数的方法,但是出现一个问题就是明明我是设置只允许连接N个,却可以连接N+1个,但第N+2个时就会失败,我没查出原因。
我的代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace TCPSERVER
{
public partial class FrmServer : Form
{
private Socket m_ServerListener = null;
private ClientInformationCls[] m_clientList;
delegate void SetTextCallback(string strText);
private const int MAX_CLIENT = 1; //client connnecting max number public FrmServer()
{
InitializeComponent();
} private static IPAddress GetServerIP()
{ IPHostEntry ieh = Dns.GetHostEntry(Dns.GetHostName()); return ieh.AddressList[0]; } private void BeginListen()
{
int intPort =8000; m_clientList=new ClientInformationCls[ MAX_CLIENT ]; IPAddress ServerIp = GetServerIP(); IPEndPoint iep = new IPEndPoint(ServerIp, intPort);
m_ServerListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_ServerListener.Bind(iep);
m_ServerListener.Listen(1);
} private void btnBeginListen_Click(object sender, EventArgs e)
{
try
{
BeginListen();
lstServerStatus.Items.Add("Server is starting listening...."); InitClientList(); Thread acceptThread = new Thread(new ThreadStart(AcceptClientThread));
acceptThread.Start();
}
catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
} private void AcceptClientThread()
{
int intClientIndex; Thread.CurrentThread.IsBackground = true; try
{
while (true)
{
intClientIndex = GetFreeClient();
if (intClientIndex != -1)
{
m_clientList[intClientIndex].IsIdle = false;
Socket clientSocket = m_ServerListener.Accept();
IPEndPoint remoEP = (IPEndPoint)clientSocket.RemoteEndPoint;
m_clientList[intClientIndex].ClientIP = remoEP.Address.ToString();
m_clientList[intClientIndex].ClientSocket = clientSocket;
SetText("connecting from " + m_clientList[intClientIndex].ClientIP); Thread DealingThread = new Thread(new ParameterizedThreadStart(RcvSndThread)); DealingThread.Start(m_clientList[intClientIndex]); }
}
} catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
} } private void RcvSndThread(object obj)
{
Thread.CurrentThread.IsBackground = true;
ClientInformationCls clientTmp = (ClientInformationCls)obj;
byte[] buffer = new byte[1024];
int intRcvCount; try
{
while (clientTmp.ClientSocket.Connected == true)
{
intRcvCount = clientTmp.ClientSocket.Receive(buffer);
SetText(Encoding.Default.GetString(buffer, 0, intRcvCount)); }
} catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
} catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
} private void InitClientList()
{
int i = 0;
for (i=0; i <= m_clientList.Length-1; i++)
{
m_clientList[i] = new ClientInformationCls();
m_clientList[i].ClientHostName="";
m_clientList[i].ClientIP = "";
m_clientList[i].Index=i;
m_clientList[i].IsIdle = true;
m_clientList[i].ClientSocket = null;
}
} private int GetFreeClient()
{
int i = 0;
for (i = 0; i <= m_clientList.Length - 1; i++)
{
if (m_clientList[i] == null) return -1;
if (m_clientList[i].IsIdle == true)
{
return i;
}
}
return -1;
} private void SetText(string strText)
{
if (this.lstServerStatus.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { strText });
}
else
{
this.lstServerStatus.Items.Add(strText);
}
} }
}
其中 ClientInformationCls是本人自定义的类,一个保存客户端SOCKET的连接信息,其中有个IsIdle属性用来记录该SOCKET是否可用
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
namespace TCPSERVER
{
class ClientInformationCls
{
private int m_intClientIndex; //client's index
private string m_strClientIP;
private string m_strClientHostName;
private bool m_blnIsIdle;
private Socket m_clientSocket;
public int Index
{
get{return m_intClientIndex;}
set{m_intClientIndex=value;}
} public string ClientIP
{
get { return m_strClientIP; }
set { m_strClientIP = value; }
} public string ClientHostName
{
get { return m_strClientHostName; }
set { m_strClientHostName = value; }
} public bool IsIdle
{
get { return m_blnIsIdle; }
set { m_blnIsIdle = value; }
}
public Socket ClientSocket
{
get { return m_clientSocket; }
set { m_clientSocket = value; }
}
}
} 我在AcceptClientThread函数中调用了
intClientIndex = GetFreeClient();
如果intClientIndex=-1的话表示不能在允许其他的客户端连接,这样就不会创建新的线程了,
现在我的问题是我明明创建了数组 m_clientList=new ClientInformationCls[ MAX_CLIENT ];
而MAX_CLIENT初始化时已经设置为1了,也就是说服务端最大的连接数为MAX_CLIENT=1,
而我测试的时候,服务端最大的连接数为MAX_CLIENT+1了,请高手帮忙看看
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货