Bootstrap

UDP日志服务器

B/S项目需要,写一个简单的UDP日志服务器。

基本功能,打印B/S后端传输的内容,有基本的时间等信息。

1.UDP服务器:简单的监听功能

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Web.Sockets.Core;

namespace LogConsole
{
    public class UDPServer
    {
        public Socket Socket { get; set; }
        public IPEndPoint IpEndPoint { get; set; }

        private int _bufferSize = 81920;
        public int BufferSize
        {
            get { return _bufferSize; }
            set { _bufferSize = value; }
        }


        private Thread threadReceive;

        public UDPServer(IPEndPoint ipEndPoint)
        {
            IpEndPoint = ipEndPoint;
        }

        public bool Start()
        {
            try
            {
                Socket = SocketHelper.GetSocket(ConnectType.UDP);
                Socket.Bind(IpEndPoint);
                StartReceive(ReceiveMsg);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return false;
            } 
        }

        public void Stop()
        {
            if (Socket != null)
            {
                Socket.Close();
                Socket = null;
            }
            if (threadReceive != null)
            {
                threadReceive.Abort();
                threadReceive = null;
            }
        }


        private void StartReceive(ThreadStart receiveFunc)
        {
            threadReceive = new Thread(receiveFunc);
            threadReceive.Start();
        }

        public void ReceiveMsg()
        {
            ReceiveMsg(null);
        }

        public void ReceiveMsg(object obj)
        {
            while (true)
            {
                try
                {
                    byte[] buffer = new byte[BufferSize];
                    int len = ReceiveMsg(buffer, null);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
            }
        }

        public int ReceiveMsg(byte[] bytMsg, object obj)
        {
            try
            {
                //byte[] buffer = new byte[BufferSize];
                IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
                EndPoint senderRemote = (EndPoint)sender;

                int len = Socket.ReceiveFrom(bytMsg, ref senderRemote);
                byte[] data = bytMsg;
                OnMessageReceived(data, senderRemote);
                return len;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                OnReceiveBreaked(Socket);
                return -1;
            }
        }

        public event Action<byte[], object> MessageReceived;
        protected void OnMessageReceived(byte[] bytMsg, object arg = null)
        {
            if (MessageReceived != null)
            {
                MessageReceived(bytMsg, arg);
            }
        }

        public event Action<Socket> ReceiveBreaked;
        protected void OnReceiveBreaked(Socket client)
        {
            if (ReceiveBreaked != null)
            {
                ReceiveBreaked(client);
            }
        }
    }
}

2.UDP客户端:就简单的发送信息功能

using System.Net;
using System.Net.Sockets;
using System.Text;
using Web.Sockets.Core;

namespace LogConsole
{
    public class UDPClient
    {
        public Socket Socket { get; set; }
        public IPEndPoint IpEndPoint { get; set; }

        public UDPClient(IPEndPoint ipEndPoint)
        {
            IpEndPoint = ipEndPoint;
            Socket = SocketHelper.GetSocket(ConnectType.UDP);
        }

        public void Send(string msg)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(msg);
            Socket.SendTo(bytes, IpEndPoint);
            //Console.WriteLine("Send:" + msg);
        }
    }
}

3.日志服务器:接收并打印日志

using System;
using System.Net;
using System.Text;

namespace LogConsole
{
    public class LogServer
    {
        private UDPServer server;
        public LogServer(IPEndPoint ipEndPoint)
        {
            server = new UDPServer(ipEndPoint);
            server.MessageReceived += Server_MessageReceived;
        }

        public bool Start()
        {
            return server.Start();
        }

        public void Stop()
        {
            server.Stop();
        }

        private void Server_MessageReceived(byte[] arg1, object arg2)
        {
            string txt = Encoding.UTF8.GetString(arg1);
            int id = txt.IndexOf('\0');
            if (id != -1)
            {
                txt = txt.Substring(0, id);
            }
            if (txt.Length > 10)
            {
                txt = GetXml(txt);
                LogInfo info=ParseLogArg(txt);
                if (info != null)
                {
                    Console.WriteLine(info);
                }
                else
                {
                    Console.WriteLine("MessageReceived:" + txt);
                }
            }
            else
            {
                Console.WriteLine("MessageReceived:" + txt);
            }
        }

        private string GetXml(string txt)
        {
            int id = txt.IndexOf("<?xml", 10);
            while (id != -1)
            {
                string xml = txt.Substring(0, id);
                ParseLogArg(xml);
                txt = txt.Substring(id);
                id = txt.IndexOf("<?xml", 10);
            }
            return txt;
        }

        private LogInfo ParseLogArg(string xml)
        {
            SerializeHelper.EnableLog = false;
            LogInfo info = SerializeHelper.LoadFromText<LogInfo>(xml);
            SerializeHelper.EnableLog = true;
            return info;
        }
    }
}

4.日志客户端:发送日志信息

using System.Net;

namespace LogConsole
{
    public class LogClient
    {
        private UDPClient client;

        public LogClient(IPEndPoint ipEndPoint)
        {
            client = new UDPClient(ipEndPoint);
        }

        public void Send(string msg)
        {
            client.Send(msg);
        }
    }
}

5.日志静态类:记录日志

using System;
using System.Diagnostics;
using System.Net;

namespace LogConsole
{
    public static class Log
    {

        public static LogClient Client;

        public static void Init(IPEndPoint ipEndPoint)
        {
            Client = new LogClient(ipEndPoint);
        }

        public static void ShowMessage()
        {

        }

        public static void Error(string tag, Exception ex, object msg)
        {
            LogInfo info = new LogInfo(LogType.Error, tag, msg);
            info.Exception = ex.ToString();
            WriteLine(info);
        }

        public static void Error(string tag, Exception ex)
        {
            LogInfo info = new LogInfo(LogType.Error, tag, "");
            info.Exception = ex.ToString();
            WriteLine(info);
        }

        public static void Error(string tag, string msg = null)
        {
            LogInfo info = new LogInfo(LogType.Error, tag, msg);
            WriteLine(info);
        }

        public static int MaxLength = 200;

        public static void Info(string tag, object msg)
        {
            LogInfo info = new LogInfo(LogType.Info, tag, msg);
            WriteLine(info);

        }

        public static void Debug(string tag, object msg = null)
        {
            LogInfo info = new LogInfo(LogType.Debug, tag, msg);
            WriteLine(info);
        }

        public static void Alarm(string tag, object msg = null)
        {
            LogInfo info = new LogInfo(LogType.Alarm, tag, msg);
            WriteLine(info);
        }

        public static void Info(string msg)
        {
            LogInfo info = new LogInfo(LogType.Info, "", msg);
            WriteLine(info);
        }

        public static void WriteLine(LogInfo info)
        {
            string line = info.ToString();
            if (MaxLength > 0 && line.Length > MaxLength)
            {
                line = line.Substring(0, MaxLength) + "。。。。。";
            }
            Trace.WriteLine(line);
            OnLogChanged(info);
        }

        private static void OnLogChanged(LogInfo info)
        {
            if (Client != null)
            {
                string xml = SerializeHelper.GetXmlText(info);
                Client.Send(xml);
            }
            if (LogChanged != null)
            {
                LogChanged(info);
            }
        }

        /// <summary>
        /// 写了日志的事件,这个很可能是在子线程中调用的,注意不能直接写在控件上。
        /// </summary>
        public static event Action<LogInfo> LogChanged;
    }
}

6.使用

    6.1服务端使用

        static void Main(string[] args)
        {
            try
            {
                int port = 6666;
                LogServer server=new LogServer(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6666));
                if (server.Start())
                {
                    Console.WriteLine(port + "端口启动监听成功");
                }
                else
                {
                    Console.WriteLine(port + "端口启动监听失败");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            Console.Read();
        }

    6.2客户端使用

        static void Main(string[] args)
        {
            try
            {
                int port = 6666;
                Log.Init(new IPEndPoint(IPAddress.Parse("127.0.0.1"), port));
                Log.Info("Program", "Main");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            Console.Read();
        }

7.可能存在问题

    1.缓存大小,UDP传输过大会截断,TCP不会。要传大数据的话,以后可以改成TCP。

    2.端口配置。

    3.多线程需求。

    4.扩展,面向接口编程。

;