一个基于Java的syslog服务器,大家都来看看啊!

前言

当时接到要开发syslog功能时,我的表情是这样的在这里插入图片描述
啥是syslog啊?我没有听说过啊?这东西有什么用啊?懵逼三连在这里插入图片描述

然后问问我大佬,他说道syslog就是巴拉巴拉的说了一大堆,我全程嗯嗯啊啊的点头,然后大佬说完了问我听懂了吗?我回复听懂了其实我是这个样子的在这里插入图片描述
我就听懂三点,第一要用java去开发,第二能支持TCP和UDP两种协议,还有可操控的,就这三点于是我开始了设计和研究啥是syslog日志服务器。

前期准备

这里写着需要准备的东西:

  1. 一双健全的手 ,能动就行;
  2. 编译器,ecplise或者idea都可以,我这里用的是ecplise;
  3. syslog解析jar包 这里用的是syslog4j的jar包,mvn项目的话maven地址 maven地址 提取码 mve8 jar地址
    注意: 假如你本地maven项目引用的镜像是阿里云你可以将版本改为0.9.46,就像我这里
    在这里插入图片描述
    4.你要懂得syslog是什么传送门

功能效果图

TCP服务器和TCP客户端运行结果:
在这里插入图片描述
TCP服务器和TCP客户端运行结果:
在这里插入图片描述
运用到项目里的结果:
在这里插入图片描述
操作页面:
在这里插入图片描述

接收到的数据只能输出到控制台的问题解决方法

这个问题困扰了我很久也一直百度但是没有找到任何的解决方法,在https://bbs.csdn.net/topics/392090474里有描述,可以复制一楼的代码运行试一试就知道了。主要问题是在于这个jar包的作者没有写出数据处理得方法,而该方法里的run里直接将信息给打印出来,不给一丝操作的机会。解决办法就是实现jar包里的SyslogServerSessionEventHandlerIF接口,然后去重写里面的event方法来达到的。该接口里提供了很多的方法,可以按照自己的需要去重写里面的方法来达到更好的效果。

具体代码

哔哔了这么久开始上代码
1.SyslogServerEventHandler类,为操作接收信息的类,继承SyslogServerSessionEventHandlerIF并重写event方法来达到。

public class SyslogServerEventHandler implements SyslogServerSessionEventHandlerIF {//extends PrintStreamSyslogServerEventHandler {

	private String syslog ;
	
	//重写event方法
	public void event(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress, SyslogServerEventIF event) {
		//判断传输时间是否存在,不存在将现在的时间设置为传输时间
		String date = (event.getDate() == null ? new Date() : event.getDate()).toString();
		//将解析日志的生成端,<<3是要该数左移动三位计算
		String facility = SyslogUtility.getFacilityString(event.getFacility()<<3);
		//讲解析日志的级别,级别越大越低
		String level = SyslogUtility.getLevelString(event.getLevel());
		//获取当前的源设备IP
		String sourceIP = getIPAddress(socketAddress.toString());
		//获取到信息主体
		String msg = event.getMessage();
		//放入信息
		setSyslog("{" + facility + "} " + date + " " + level + " " + event.getMessage()+ " " +sourceIP );
		try {
			//打印信息
			System.out.println(getSyslog());
		} catch (UnsupportedEncodingException e) {
			System.err.println("UnsupportedEncodingException");
		}
		
	}
	public String getSyslog() throws UnsupportedEncodingException {
		return new String(syslog.getBytes(),"UTF-8");
	}
	public void setSyslog(String syslog) {
		this.syslog = syslog;
	}
	//获取到该字符串里的ip地址
	private String getIPAddress(String bString)
	{
		String regEx="((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)";
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(bString);
		String result = "";
		while (m.find()) {
		result=m.group();
		
		break;  
		}
		return result;
	}
	
	
	@Override
	public void initialize(SyslogServerIF syslogServer) {}
	@Override
	public void destroy(SyslogServerIF syslogServer) {}
	@Override
	public Object sessionOpened(SyslogServerIF syslogServer, SocketAddress socketAddress) {return null;}
	@Override
	public void exception(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress,Exception exception) {}
	@Override
	public void sessionClosed(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress,boolean timeout) {}
}
  1. TCP服务器 我喜欢用线程的方式启动,因为不用切来却去
public class TCPSyslogServerFinal implements Runnable {

	private static TCPSyslogServerFinal TCPSyslogServerFinal = null;
	//syslog服务器配置文件用于服务器关闭
	private SyslogServerIF serverIf = null ;
	
	public SyslogServerIF getServerIF() {
		return serverIf;
	}
	private void setServerIF(SyslogServerIF serverIF) {
		this.serverIf = serverIF;
	}
	
	private TCPSyslogServerFinal(){}
	//用单例模式去书写
	public static synchronized TCPSyslogServerFinal getTCPSyslogServer()
	{
		if(TCPSyslogServerFinal == null)
		{
			TCPSyslogServerFinal = new TCPSyslogServerFinal();
		}
		return TCPSyslogServerFinal;
	}
	@Override
	public void run() {
		//实例化接收处理方法
		SyslogServerEventHandlerIF eventHandler = new SyslogServerEventHandler();
		//传入TCP协议参数实例化具体服务器
		SyslogServerIF serverIF = SyslogServer.getInstance("tcp");
		//从服务器里获取配置信息变量
		SyslogServerConfigIF config = serverIF.getConfig();
		//设置监听地址0.0.0.0为监听网络内全部地址
		config.setHost("0.0.0.0");
		//设置监听地址为514,514为syslog默认地址
		config.setPort(514);
		//放入接收方法
		config.addEventHandler(eventHandler);
		//初始化服务器
		serverIF.initialize("tcp",config);
		System.out.println("server start tcp");
		//设置服务器变量,用来外部调用关闭
		setServerIF(serverIF);
		//服务器启动
		serverIF.run();
	}
}
  1. UDP服务器 我喜欢用线程的方式启动,不同的地方就是在处传输的地方改为UDP
public class UDPSyslogServerFinal implements Runnable {

	private static UDPSyslogServerFinal UDPSyslogServerFinal = null;
	//syslog服务器配置文件用于服务器关闭
	private SyslogServerIF serverIf = null ;
	
	public SyslogServerIF getServerIF() {
		return serverIf;
	}
	private void setServerIF(SyslogServerIF serverIF) {
		this.serverIf = serverIF;
	}
	
	private UDPSyslogServerFinal(){}
	//用单例模式去书写
	public static synchronized UDPSyslogServerFinal getUDPSyslogServer()
	{
		if(UDPSyslogServerFinal == null)
		{
			UDPSyslogServerFinal = newUDPSyslogServerFinal();
		}
		return UDPSyslogServerFinal;
	}
	@Override
	public void run() {
		//实例化接收处理方法
		SyslogServerEventHandlerIF eventHandler = new SyslogServerEventHandler();
		//传入UDP协议参数实例化具体服务器  就是这个位置不同,如果你闲麻烦可以用自己优化一下算法然后将两个合为一个
		SyslogServerIF serverIF = SyslogServer.getInstance("udp");
		//从服务器里获取配置信息变量
		SyslogServerConfigIF config = serverIF.getConfig();
		//设置监听地址0.0.0.0为监听网络内全部地址
		config.setHost("0.0.0.0");
		//设置监听地址为514,514为syslog默认地址
		config.setPort(514);
		//放入接收方法
		config.addEventHandler(eventHandler);
		//初始化服务器
		serverIF.initialize("udp",config);
		System.out.println("server start udp");
		//设置服务器变量,用来外部调用关闭
		setServerIF(serverIF);
		//服务器启动
		serverIF.run();
	}
}

4.客户端 ClientClass,我喜欢用线程的方式去实现

public class ClientClass implements Runnable{
	//控制循环结束的
	private boolean flag = true;
	private static ClientClass ClientClass = null;
	private ClientClass () {
	}
	public static synchronized ClientClass getClient()
	{
		if(ClientClass == null)
			ClientClass = new ClientClass ();
		return ClientClass ;
	}
	@Override
	public void run() {
		try {  
			//初始化标识位
			flag = true;
			//以传输名称的形势来传输实例化的协议类型
			String prot = Thread.currentThread().getName();  
            //获取syslog的操作类,使用udp协议。syslog支持"udp", "tcp", "unix_syslog", "unix_socket"协议  
            SyslogIF syslog = Syslog.getInstance(prot);   
            //设置syslog服务器端地址   地址为之前你服务器的地址
            syslog.getConfig().setHost("xx.xx.xx.xx");  
            //设置syslog接收端口,默认514  
            syslog.getConfig().setPort(514);  
            //拼接syslog日志
            String str = "operator Protocol "+ Thread.currentThread().getName();  
            System.out.println("+++++++++++++start++++++++++++");
            while(flag) {
            	//等级为debug
	            syslog.log(SyslogConstants.LEVEL_DEBUG, URLDecoder.decode(str,"utf-8")); 
	            //给程序缓冲时间,没有缓冲时间接受不到数据
	            Thread.sleep(100);
            }
           System.out.println(Thread.currentThread().getName()+" end");
        } catch (Exception e) { 
        	System.err.println("出错了");
        	e.printStackTrace();
        } 
     }
     public void shutdown() {
		try {
			//线程停止
			Thread.sleep(2000);
			//改变标识位
			flag = false;
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

5.测试类TestServerClass,运行main方法的测试类

@SuppressWarnings("unused")
public class TestServerClass implements Runnable{
	public static void main(String[] args) throws Exception {
		//获取UDP服务器线程
		Thread UDPServer = new Thread(UDPSyslogServerFinal.getUDPSyslogServer(),"这是UDP服务器");
		//获取TCP服务器线程
		Thread TCPServer = new Thread(TCPSyslogServerFinal.getTCPSyslogServer(),"这是TCP服务器");
		//获取UDP客户端线程
		Thread UDPClient = new Thread(ClientClass.getClient(),"UDP");
		//获取TCP客户端线程
		Thread TCPClient = new Thread(ClientClass.getClient(),"TCP");
		//启动线程
		UDPServer.start();
		UDPClient.start();
		TCPServer.start();
		TCPClient.start();
		//运行十秒后关闭
		Thread.sleep(10*1000);
		//关闭服务器
		UDPSyslogServerFinal.getUDPSyslogServer().getServerIF().shutdown();
		TCPSyslogServerFinal.getTCPSyslogServer().getServerIF().shutdown();
		//关闭客户端
		ClientClass.getClient().shutdown();
	}
}

结语

文章到这里就结束啦,写这个文章的初衷是因为自己想帮助那些想找java的syslog服务器却找不到的那些人。真的,在网上试着去百度、翻阅各种网站的博客都找不到解决的方法,这种感觉真的很崩溃。我的所有有灵感都来自于https://bbs.csdn.net/topics/392090474这个帖子,这个帖子到我发布的时候还是没有完结,所以我打算将解决方法写出来,然后去完结那个帖子,也希望能帮助那些看的人。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_33248254/article/details/89403394