日期:2014-05-18  浏览次数:21063 次

IO完成端口是如何做的
长连接的简单模型大概是这样的
C# code

        private int _port = 6868;
        private const int _maxPacket = 64;
        private TcpListener _tcpl = null;
        public string userip;
        public Hashtable _transmit_tb = new Hashtable();


        static void Main(string[] args)
        {
            Listen l = new Listen();
            try
            {
                l.startup();
            }
            catch (Exception) {  }
        }
        public void startup()
        {
            IPAddress _ip = Dns.GetHostAddresses(Dns.GetHostName())[0];
            _tcpl = new TcpListener(_ip, _port);
            _tcpl.Start();
            Console.WriteLine(string.Format("the server ip is {0},and the port is {1}", _ip, _port));
            Console.WriteLine("server has been started,is listening...");
            while (true)
            {
                byte[] packetBuff = new byte[_maxPacket];
                Socket newClient = _tcpl.AcceptSocket();
                IPEndPoint ip = (IPEndPoint)newClient.RemoteEndPoint;
                //userip = ip.Address.ToString().TrimEnd() + ":" + ip.Port;
                userip = ip.Address.ToString().TrimEnd();
                if (_transmit_tb.Count != 0 && _transmit_tb.ContainsKey(userip))
                {
                    _transmit_tb.Remove(userip);
                    _transmit_tb.Add(userip, newClient);
                }
                else
                    _transmit_tb.Add(userip, newClient);
                string svrlog = string.Format("new ip {0} at {1} is connected,current online number is {2}",
 userip + ":" + ip.Port, DateTime.Now, _transmit_tb.Count);
                Console.WriteLine(svrlog);
                Thread clientthread = new Thread(new ParameterizedThreadStart(threadfun));
                clientthread.Start(userip);
                clientthread.IsBackground = true;
                Thread.Sleep(200);
            }
        }

        private void threadfun(object obj)
        {
            Socket clientsocket = _transmit_tb[obj] as Socket;
            while (true)
            {
                try
                {
                    if (clientsocket == null || clientsocket.Available < 1)
                    {
                        Thread.Sleep(300);
                        continue;
                    }
                    byte[] _cmdBuff = new byte[128];
                    int size = clientsocket.Receive(_cmdBuff);
                    //在这里处理收到的数据

                    //向客户端发送数据
                    clientsocket.Send(_cmdBuff);
                }
                catch (SocketException)
                {
                    _transmit_tb.Remove(obj);
                    clientsocket.Close();
                    Thread.CurrentThread.Abort();
                }
            }
        }


在主线程里监听客户端连接请求,然后每个连接到服务器的用户都建立一个线程,在这个线程里再死循环收客户发来的数据包,做处理以后再回客户端数据包,这种模式显然用户很多的时候是不行的,太耗服务器资源。
请高手帮忙把这段代码改成IO完成端口的,可以接收同时5000人以上用户的连接。
请给详细代码,写上注释。

------解决方案--------------------
http://topic.csdn.net/t/20040512/08/3056877.html
------解决方案--------------------
其实C#的很多异步操作已经使用了IO Complemention,你只要简单的BeginReceive/EndReceive就可以了。.Net内部会帮你把IO Complemtion发送到线程池并调用你提供的回调函数。

比如下面的代码。
在实验中保持Server运行,同时运行多次Client,你可以发现.Net并不一定需要多个线程来服务多个客户,在保持快速响应的同时,尽可能复用可用线程(可能最终一个就够了):
C# code

// Server.cs
class Server
{
    static void Main(string[] args)
    {
        TcpListener listener = new TcpListener(IPAddress.Any, 4567);
        listener.Start();
        while (true)
        {
            Socket socket = listener.AcceptSocket();
            StateObject so = new StateObject() { socket = socket };
            so.socket.BeginReceive(so