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.扩展,面向接口编程。