必须填写至少10个字的日志
nnhy 编写于 2012-07-27 18:48:21
X
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using NewLife.Linq;
using NewLife.Net.Common;
using NewLife.Net.Sockets;
using NewLife.Threading;
using NewLife.Net.Tcp;

namespace NewLife.Net.Application
{
    /// <summary>网络应用程序测试</summary>
    public static class AppTest
    {
        #region 基础服务测试
        /// <summary>开始测试</summary>
        public static void Start()
        {
            StartServer();
            StartClient();
        }

        /// <summary>开始测试</summary>
        public static void StartServer()
        {
            var ts = new Type[] { typeof(ChargenServer), typeof(DaytimeServer), typeof(DiscardServer), typeof(EchoServer), typeof(TimeServer) };
            //var ts = new Type[] { typeof(EchoServer) };
            var list = new List<NetServer>();
            foreach (var item in ts)
            {
                var server = Activator.CreateInstance(item) as NetServer;
                server.Start();
                //server.Servers.ForEach(s => s.UseThreadPool = false);
                foreach (var s in server.Servers)
                {
                    s.UseThreadPool = false;
                }
                list.Add(server);
            }
        }

        /// <summary>开始测试</summary>
        public static void StartClient()
        {
            StartEchoServer(7);
            StartDaytimeServer(13);
            StartTimeServer(37);
            StartDiscardServer(9);
            StartChargenServer(19);
        }

        static AutoResetEvent _are = new AutoResetEvent(true);
        static void OnReceived(object sender, ReceivedEventArgs e)
        {
            var session = sender as ISocketSession;
            Console.WriteLine("客户端{0} 收到 [{1}] {2}", session, e.Stream.Length, e.Stream.ToStr());

            _are.Set();
        }

        static void OnError(object sender, NetEventArgs e)
        {
            if (e.SocketError == SocketError.OperationAborted) return;

            if (e.SocketError != SocketError.Success || e.Error != null)
                Console.WriteLine("客户端{0} {3}错误 {1} {2}", sender, e.SocketError, e.Error, e.LastOperation);
            else
                Console.WriteLine("客户端{0} {1}断开!", sender, e.LastOperation);
        }

        static void TestSend(String name, NetUri uri, Boolean isAsync, Boolean isSendData, Boolean isReceiveData)
        {
            Console.WriteLine();

            String msg = String.Format("{0}Test_{1}_{2}!", name, uri.ProtocolType, isAsync ? "异步" : "同步");
            var session = NetService.CreateSession(uri);
            session.Host.Error += new EventHandler<NetEventArgs>(OnError);
            //session.Host.Socket.ReceiveTimeout = 3000;
            if (isAsync && isReceiveData)
            {
                _are.Reset();
                session.Received += new EventHandler<ReceivedEventArgs>(OnReceived);
                session.ReceiveAsync();
            }
            if (isSendData) session.Send(msg);
            if (isReceiveData)
            {
                if (!isAsync)
                {
                    try
                    {
                        Console.WriteLine("客户端" + session + " " + session.ReceiveString());
                    }
                    catch (Exception ex)
                    {
                        Debug.Fail("同步超时!" + ex.Message);
                    }
                }
                else
                {
                    if (!_are.WaitOne(2000)) Debug.Fail("异步超时!");
                }
            }
            session.Dispose();
            if (session.Host != null) session.Host.Dispose();
            Console.WriteLine("结束!");
        }

        static void TestSends(String name, IPEndPoint ep, Boolean isSendData, Boolean isReceiveData = true)
        {
            if (ep.AddressFamily == AddressFamily.InterNetworkV6) return;

            Console.WriteLine();
            Console.WriteLine("{0}:", name);
            //TestSend(name, ProtocolType.Udp, ep, false, isSendData, isReceiveData);
            //TestSend(name, ProtocolType.Udp, ep, true, isSendData, isReceiveData);
            //TestSend(name, ProtocolType.Tcp, ep, false, isSendData, isReceiveData);
            //TestSend(name, ProtocolType.Tcp, ep, true, isSendData, isReceiveData);
            var uri = new NetUri(ProtocolType.Udp, ep);
            TestSend(name, uri, false, isSendData, isReceiveData);
            TestSend(name, uri, true, isSendData, isReceiveData);
            uri.ProtocolType = ProtocolType.Tcp;
            TestSend(name, uri, false, isSendData, isReceiveData);
            TestSend(name, uri, true, isSendData, isReceiveData);

            GC.Collect();
        }

        static void StartEchoServer(Int32 port)
        {
            IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, port);

            TestSends("Echo", ep, true);

            ep = new IPEndPoint(IPAddress.IPv6Loopback, port);

            TestSends("Echo IPv6", ep, true);
        }

        static void StartDaytimeServer(Int32 port)
        {
            IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, port);

            TestSends("Daytime", ep, true);

            ep = new IPEndPoint(IPAddress.IPv6Loopback, port);

            TestSends("Daytime IPv6", ep, true);
        }

        static void StartTimeServer(Int32 port)
        {
            IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, port);

            TestSends("Time", ep, true);

            ep = new IPEndPoint(IPAddress.IPv6Loopback, port);

            TestSends("Time IPv6", ep, true);
        }

        static void StartDiscardServer(Int32 port)
        {
            IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, port);

            TestSends("Discard", ep, true, false);

            ep = new IPEndPoint(IPAddress.IPv6Loopback, port);

            TestSends("Discard IPv6", ep, true, false);
        }

        static void StartChargenServer(Int32 port)
        {
            IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, port);

            TestSends("Chargen", ep, true);

            ep = new IPEndPoint(IPAddress.IPv6Loopback, port);

            TestSends("Chargen IPv6", ep, true);
        }
        #endregion

        #region TCP大量连接测试
        /// <summary>TCP大量连接测试</summary>
        public static void TcpConnectionTest()
        {
            while (true)
            {
                Console.Write("请选择模式:(1,服务端 2,客户端)");
                var str = Console.ReadLine();

                if (str == "1")
                {
                    TestServer();
                    break;
                }
                else if (str == "2")
                {
                    TestClient();
                    break;
                }
            }
        }

        static NetServer server = null;
        static void TestServer()
        {
            Int32 port = ReadInt("请输入监听端口:", 1, 65535);

            // 扩大事件池
            NetEventArgs.Pool.Max = 200000;

            server = new NetServer();
            server.ProtocolType = ProtocolType.Tcp;
            server.Port = port;
            server.Received += OnReceived;
            // 最大不活跃时间设为10分钟
            foreach (TcpServer item in server.Servers)
            {
                item.MaxNotActive = 10 * 60;
            }
            server.Start();
            server.EnableLog = false;

            ThreadPoolX.QueueUserWorkItem(ShowStatus);

            Console.WriteLine("服务端准备就绪,任何时候任意键退出服务程序!");
            Console.ReadKey(true);

            server.Dispose();
        }

        /// <summary>已重载。</summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void OnReceived(object sender, NetEventArgs e)
        {
            var session = e.Session;

            //if (e.BytesTransferred > 100)
            //    Console.WriteLine("Echo {0} [{1}]", session.RemoteUri, e.BytesTransferred);
            //else
            //    Console.WriteLine("Echo {0} [{1}] {2}", session.RemoteUri, e.BytesTransferred, e.GetString());
            var msg = "";
            if (e.BytesTransferred > 100)
                msg = String.Format("Echo {0} [{1}]", session.RemoteUri, e.BytesTransferred);
            else
                msg = String.Format("Echo {0} [{1}] {2}", session.RemoteUri, e.BytesTransferred, e.GetString());

            session.Send(e.Buffer, e.Offset, e.BytesTransferred);
        }

        static void ShowStatus()
        {
            var pool = NetEventArgs.Pool;

            while (true)
            {
                try
                {
                    var asyncCount = 0;
                    foreach (var item in server.Servers)
                    {
                        asyncCount += item.AsyncCount;
                    }
                    //foreach (var item in server.Sessions.Values.ToArray())
                    //{
                    //    var remote = (item as IProxySession).Remote;
                    //    if (remote != null) asyncCount += remote.Host.AsyncCount;
                    //}

                    Int32 wt = 0;
                    Int32 cpt = 0;
                    ThreadPool.GetAvailableThreads(out wt, out cpt);
                    Int32 threads = Process.GetCurrentProcess().Threads.Count;

                    var color = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("异步:{0} 会话:{1} Thread:{2}/{3}/{4} Pool:{5}/{6}/{7}", asyncCount, server.Sessions.Count, threads, wt, cpt, pool.StockCount, pool.FreeCount, pool.CreateCount);
                    Console.ForegroundColor = color;
                }
                catch { }

                Thread.Sleep(3000);
            }
        }

        //static Thread[] threads;
        static void TestClient()
        {
            Console.Write("请输入服务器地址:");
            var host = Console.ReadLine();
            var port = ReadInt("请输入服务器端口:", 1, 65535);

            var ep = NetHelper.ParseEndPoint(host, port);
            var uri = new NetUri(ProtocolType.Tcp, ep);

            Console.WriteLine("开始测试连接{0}……", uri);

            var session = NetService.CreateSession(uri);
            session.Send("Hi");
            var rs = session.ReceiveString();
            session.Dispose();
            if (rs.IsNullOrWhiteSpace())
            {
                Console.WriteLine("连接失败!");
                return;
            }

            var threadcount = ReadInt("请输入线程数(建议20):", 1, 10000);
            var perthread = ReadInt("请输入每线程连接数(建议500):", 1, 10000);
            //var time = ReadInt("请输入连接间隔(毫秒,建议10毫秒):", 1, 10000);
            var time = 10;

            var threads = new Thread[threadcount];
            for (int i = 0; i < threadcount; i++)
            {
                var th = new Thread(ClientProcess);
                th.IsBackground = true;
                th.Priority = ThreadPriority.BelowNormal;
                th.Name = "Client_" + (i + 1);

                threads[i] = th;
                var p = new TCParam() { ID = i + 1, Count = perthread, Period = time, Uri = uri };
                th.Start(p);

                Thread.Sleep(100);
            }
        }

        static void ClientProcess(Object state)
        {
            var p = state as TCParam;

            var msg = String.Format("Hi I am {0}!", p.ID);

            var sessions = new ISocketSession[p.Count];
            for (int k = 0; k < 100; k++)
            {
                Console.WriteLine("第{1}轮处理:{0}", p.ID, k + 1);

                for (int i = 0; i < p.Count; i++)
                {
                    try
                    {
                        var session = sessions[i];
                        if (session == null || session.Disposed)
                        {
                            session = NetService.CreateSession(p.Uri);
                            // 异步接收,什么也不做
                            //session.Received += (s, e) => { };
                            session.ReceiveAsync();

                            sessions[i] = session;
                        }

                        session.Send(msg);
                    }
                    catch { }

                    if (p.Period > 0) Thread.Sleep(p.Period);
                }
            }
        }

        class TCParam
        {
            public Int32 ID;
            public Int32 Count;
            public Int32 Period;

            public NetUri Uri;
        }

        static Int32 ReadInt(String title, Int32 min, Int32 max)
        {
            if (String.IsNullOrEmpty(title))
                title = "请输入数字:";
            else if (title[title.Length - 1] != ':')
                title += ":";

            Int32 n = 0;
            while (n < min || n > max)
            {
                Console.Write(title);
                var str = Console.ReadLine();
                if (!String.IsNullOrEmpty(str)) Int32.TryParse(str, out n);
            }
            return n;
        }
        #endregion
    }
}