谢谢。现在的程序如下
//这是一个新线程
private void AcceptConnect()
{
//获取本机所有IP地址DD
IPAddress[] ip = Dns.GetHostAddresses(Dns.GetHostName());
listener = new TcpListener(ip[0], 51888);
//开始侦听客户端
listener.Start(); //然后新线程始终在这里循环
while (isExit == false)
{
try
{
//等.WaitOne()来阻塞线程。
allDone.Reset(); //引用在异步操作完成时调用的回调方法
AsyncCallback callback = new AsyncCallback(AcceptTcpClientCallback); listBoxStatus.Invoke(setListBoxCallback, "开始等待客户连接"); //开始一个异步操作接受传入的连接尝试
listener.BeginAcceptTcpClient(callback, listener); //阻塞当前线程,直到收到客户连接信号
allDone.WaitOne();
}
catch (Exception err)
{
listBoxStatus.Invoke(setListBoxCallback, err.Message);
break;
}
}
//
}
然后系统在接收到一个客户端连接后,自动调用回调函数如下
private void AcceptTcpClientCallback(IAsyncResult ar)
{
try
{
//允许线程需要进行
allDone.Set(); TcpListener myListener = ar.AsyncState as TcpListener; TcpClient client = myListener.EndAcceptTcpClient(ar); //偿试以非同步方式接入连接,并建立新的TcpClient处理与远程主机通讯 //UI刷新
listBoxStatus.Invoke(setListBoxCallback,"已接受客户连接:" + client.Client.RemoteEndPoint);
comboBox1.Invoke(setComboBoxCallback, client.Client.RemoteEndPoint.ToString()); //读取数据
ReadWriteObject readWriteObject = new ReadWriteObject(client);
clientList.Add(readWriteObject);
SendString(readWriteObject, "服务器已经接受连接,请通话"); readWriteObject.netStream.BeginRead(readWriteObject.readBytes,0,
readWriteObject.readBytes.Length, ReadCallback, readWriteObject); //每接收一个客户端,加1
number_thread = number_thread + 1;
textBox1.Invoke(setLableThreadCallback, number_thread.ToString());//在UI线程上显示
}
catch (Exception err)
{
listBoxStatus.Invoke(setListBoxCallback, err.Message);
return;
}
}
这里readWriteObject发送、接收信息,与客户端进行通讯。这样连续接入10个客户端,并且每个客户端进行通讯。请问,此时这10个客户端是共用一个线程,还是系统给它们各自开辟线程进行 “发送、接收”操作的呢?
//这是一个新线程
private void AcceptConnect()
{
//获取本机所有IP地址DD
IPAddress[] ip = Dns.GetHostAddresses(Dns.GetHostName());
listener = new TcpListener(ip[0], 51888);
//开始侦听客户端
listener.Start(); //然后新线程始终在这里循环
while (isExit == false)
{
try
{
//等.WaitOne()来阻塞线程。
allDone.Reset(); //引用在异步操作完成时调用的回调方法
AsyncCallback callback = new AsyncCallback(AcceptTcpClientCallback); listBoxStatus.Invoke(setListBoxCallback, "开始等待客户连接"); //开始一个异步操作接受传入的连接尝试
listener.BeginAcceptTcpClient(callback, listener); //阻塞当前线程,直到收到客户连接信号
allDone.WaitOne();
}
catch (Exception err)
{
listBoxStatus.Invoke(setListBoxCallback, err.Message);
break;
}
}
//
}
然后系统在接收到一个客户端连接后,自动调用回调函数如下
private void AcceptTcpClientCallback(IAsyncResult ar)
{
try
{
//允许线程需要进行
allDone.Set(); TcpListener myListener = ar.AsyncState as TcpListener; TcpClient client = myListener.EndAcceptTcpClient(ar); //偿试以非同步方式接入连接,并建立新的TcpClient处理与远程主机通讯 //UI刷新
listBoxStatus.Invoke(setListBoxCallback,"已接受客户连接:" + client.Client.RemoteEndPoint);
comboBox1.Invoke(setComboBoxCallback, client.Client.RemoteEndPoint.ToString()); //读取数据
ReadWriteObject readWriteObject = new ReadWriteObject(client);
clientList.Add(readWriteObject);
SendString(readWriteObject, "服务器已经接受连接,请通话"); readWriteObject.netStream.BeginRead(readWriteObject.readBytes,0,
readWriteObject.readBytes.Length, ReadCallback, readWriteObject); //每接收一个客户端,加1
number_thread = number_thread + 1;
textBox1.Invoke(setLableThreadCallback, number_thread.ToString());//在UI线程上显示
}
catch (Exception err)
{
listBoxStatus.Invoke(setListBoxCallback, err.Message);
return;
}
}
这里readWriteObject发送、接收信息,与客户端进行通讯。这样连续接入10个客户端,并且每个客户端进行通讯。请问,此时这10个客户端是共用一个线程,还是系统给它们各自开辟线程进行 “发送、接收”操作的呢?
因为从程序代码上后,每次每个客户端接入时,只调用过它一次,并没有第二次、第三次调用它。
而每个客户端与服务端连接上后,就可以任意次通讯了。为什么?
你的 AcceptConnect 中不应该写“循环、阻塞”的语句。你在异步Read的程序中写的是对的,没有搞什么循环、阻塞。过程代码立刻结束,把 I/O 线程立即释放(回线程池),这是很重要的事情。绝不能占着 I/O 线程在那里做一堆 Worker 线程的事情,更不应该“循环、阻塞”线程。
看不到你的 readCallback 中的代码,不知道程序设计的逻辑是什么。如果你看不到继续调用它,那么可能是这个程序的设计者:
1. 是在写一个“短链接”通讯程序,因此只要“读”数据然后“写”数据,之后就把连接关闭了。
2. 他没有考虑一次 Read 可能不能读取完整的消息的问题,他以为一定可以再一次 Read 时得到客户端发来的所有数据。这第一点,是可以理解的。而第二点,可能是个 bug,当网路不是很好的时候就会出现读取数据不足、而需要多次Read的问题。
异步处理方式,即使你的服务端使用(仅仅)一个端口连接10万个在线客户端,可能占用线程也就是10几个。而使用线程少,基本上就说明你的程序设计得不纠缠CPU了。