一个C#简单的异步服务器

没研究太深,仅仅是接收客户端连接和读数据。

     服务器,所有异步方法会自动放到后台线程池去处理,无需我们代码去创建线程:

    internal class ClientMessage
    {
        public ClientMessage(TcpClient client,int buffSize)
        {
            Client = client;
            Data = new byte[buffSize];
        }
        public TcpClient Client { get; set; }
        public byte[] Data { get;set;}
    }
    
       public class TcpServer
    {
        private readonly ConcurrentDictionary<string, TcpClient> _clients = new ConcurrentDictionary<string, TcpClient>();
        private readonly List<string> _failedClientKey = new List<string>();
        TcpListener _tcpListener;


        /// <summary>
        /// 处理连接请求
        /// </summary>
        /// <param name="result"></param>
        void AsyncAccept(IAsyncResult result)
        {
            //透穿参数监听器,就是成员_tcpListener
            var tcpListener = (TcpListener)result.AsyncState;


            //得到客户端
            var client = tcpListener.EndAcceptTcpClient(result);


            Console.WriteLine("A client connected:" + client.Client.RemoteEndPoint.ToString());


            var msg = new ClientMessage(client, client.ReceiveBufferSize);


            //去异步读数据
            ReadFromClient(msg);


            _clients.TryAdd(client.Client.RemoteEndPoint.ToString(), client);


            //异步接受下一个请求
            Accept();
        }


        void AsyncRead(IAsyncResult result)
        {
            var msg = result.AsyncState as ClientMessage;
            try
            {
                var len = msg.Client.Client.EndReceive(result);
                var message = Encoding.ASCII.GetString(msg.Data, 0, len);
                Console.WriteLine("Received:" + message);


                //读下一次的数据
                ReadFromClient(msg);
            }
            catch(SocketException e)
            {
                //客户端关闭
                Console.WriteLine(e.Message + ":" + msg.Client.Client.RemoteEndPoint);
                _clients.TryRemove(msg.Client.Client.RemoteEndPoint.ToString(),out var client);
                client.Close();
            }
        }


        void ReadFromClient(ClientMessage msg)
        {
            var result = msg.Client.Client.BeginReceive(
                msg.Data, 0, msg.Data.Length, 
                SocketFlags.None, AsyncRead, msg);
        }


        public void Accept()
        {
            //异步接收客户端连接
            var result = _tcpListener.BeginAcceptTcpClient(AsyncAccept, _tcpListener);
        }


        public void Start(int port)
        {
            _tcpListener = new TcpListener(IPAddress.Any, port);
            _tcpListener.Start(10);
            Accept();
        }


        void AsyncSend(IAsyncResult result)
        {
            var client = result.AsyncState as TcpClient;
            var num = client?.Client.EndSend(result);
            if (num.HasValue)
            {
                Console.WriteLine("sent data bytes:" + num);
            }
        }


        public void Send(string msg)
        {
            var data = Encoding.ASCII.GetBytes(msg);


            foreach (var client in _clients)
            {
                try
                {
                    var result = client.Value.Client.BeginSend(data, 0, data.Length, SocketFlags.None,
                        AsyncSend, client.Value);
                }
                catch (SocketException e)
                {
                    Console.WriteLine(e.Message + ":" + client.Key);
                    client.Value.Close();
                    _failedClientKey.Add(client.Key);
                }
            }


            if (_failedClientKey.Any())
            {
                foreach (var key in _failedClientKey)
                {
                    _clients.TryRemove(key,out _);
                }
                _failedClientKey.Clear();
            }
        }
    }


     
      class Program
    {
        static void Main(string[] args)
        {
            var tcpServer = new TcpServer();
            try
            {
                tcpServer.Start(args.Length > 1 ? int.Parse(args[1]) : 13000);
                Console.WriteLine("server start");
            }
            catch(Exception e)
            {
                Console.WriteLine("server start failed");
            }


            while (true)
            {
                var str = Console.ReadLine();
                if (string.Compare(str, "exit") != 0)
                {
                    tcpServer.Send(str);
                }
                else
                {
                    break;
                }
            }
        }
    }


     测试用的客户端:

     

    public class MyTcpClient
    {
        private readonly TcpClient _client = new TcpClient();
        private byte[] _data;


        public void Start(string ip, int port)
        {
            _client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 13000));
            _data = new byte[_client.ReceiveBufferSize];
            Receive();
        }


        void Receive()
        {
            _client.Client.BeginReceive(_data, 0, _data.Length, SocketFlags.None, AsyncReceive, null);
        }


        void AsyncReceive(IAsyncResult result)
        {
            try
            {
                var num = _client.Client.EndReceive(result);
                var message = Encoding.ASCII.GetString(_data, 0, num);
                Console.WriteLine("Received:" + message);
                Receive();
            }
            catch (SocketException e)
            {
                Console.WriteLine(e);
                _client.Close();
            }
        }


        void AsyncSend(IAsyncResult result)
        {
            var client = result.AsyncState as TcpClient;
            var num = client?.Client.EndSend(result);
            if (num.HasValue)
            {
                Console.WriteLine("sent data bytes:" + num);
            }
        }


        public void Send(string msg)
        {
            var data = Encoding.ASCII.GetBytes(msg);
            try
            {
                var result = _client.Client.BeginSend(data, 0, data.Length, SocketFlags.None,
                    AsyncSend, _client);
            }
            catch (SocketException e)
            {
                Console.WriteLine(e);
                _client.Close();
            }
        }
    }




    class Program
    {
        static void Main(string[] args)
        {
            var client = new MyTcpClient();
            try
            {
                client.Start("127.0.0.1", 13000);
                Console.WriteLine("connected");

                while (true)
                {
                    var str = Console.ReadLine();
                    if (string.Compare(str, "exit") != 0)
                    {
                        client.Send(str);
                    }
                    else
                    {
                        break;
                    }
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值