UDP高频发包,导致信息丢失,使用队列处理

在嵌入式单板环境下,c给java虚拟机使用UDP发包,超过140包/s时,就会丢包,严重影响业务。

使用队列处理,主要解决以下问题,

1、不同事件类型放在一个队列,因为有些事件的发包频率不快,但是比较重要。

2、适用于有多个client给一个server在同一端口高频发不同类型的包。

3、不断从队列中取消息并进行处理。

程序开始运行之前先初始化消息处理线程,使其一直阻塞在等待入队元素状态:

private class PushDispatcher extends Thread {
	private boolean isDone = false;

	public void shutdown() {
		isDone = true;
	}

	public PushDispatcher() {
		this.setDaemon(true);
		log.track(LoggerI.SYSDEBUG,"SDK event PushDispatcher start ");
	}

	@Override
	public void run() {
		
		while (!isDone) {
			JSONObject pushData = eventCache.fetchPush();向队列一直请求元素,队列为空则一直阻塞。
			
			/**处理接收到的事件推送*/
			JSONObject format = pushData.getJSONObject("format");
			JSONArray bundleName = pushData.getJSONArray("bundlename");
			String event = pushData.getString("Event");
			for (int i = 0; i < bundleName.length(); i++)
			{
				String name = bundleName.getString(i);
				udpMonitor.eventsend(name, format.toString(), event);这里向第三方插件发送消息
			}						
		}

		log.track(LoggerI.SYSDEBUG,"SDK event PushDispatcher offline ");
	}
}
队列实现:

public class EventCache {
此队列是单独的消息直接入队
private List<JSONObject> pushs = new LinkedList<JSONObject>();
此队列是两种消息入队列
    private List<MsgObject> msgPushs = new LinkedList<MsgObject>();

public void msgPutPush(MsgObject obj) throws Exception
{
锁定队列,之后向入队,通知队列中已经有元素,激活队列的wait。
    synchronized (msgPushs)
    {
        msgPushs.add(obj);
        msgPushs.notify();
    }
}

public MsgObject msgFetchPush()
{
    MsgObject getMsgPushs = null;
    
    synchronized(msgPushs)
    { 
锁定队列,队列为空,死等待,notify通知之后,出队首元素。
        if(msgPushs.isEmpty())
        {
            try
                {
                    msgPushs.wait();
                    getMsgPushs = msgPushs.remove(0);
                }
                catch (InterruptedException e)
                {
                    log.error("fetch msgPush error, " + e);
                }
        }
    }
    log.debug("out fetch msgPush : " + getMsgPushs.toString());
    return getMsgPushs;
    //pushs出队入队类似
}
}


服务端分发消息:

while (true)
{
	byte[] data = new byte[1024];
	DatagramPacket packet = new DatagramPacket(data, data.length);
	server.receive(packet);// 此方法在接收到数据报之前会一直阻塞
	// 读取数据
	String info = new String(data, 0, packet.getLength());
	log.track(LoggerI.SYSDEBUG,"Client message:" + info);
	
	JSONObject dataJson = new JSONObject(info);
	String event = dataJson.getString("Event");
	log.debug("Message head:" + event);
	
	if (event.equals("1"))
	{
	}
	else if (event.equals("2"))
	{
		
	}
	else if (event.equals("3p"))
	{
		++countP;
		log.debug("msg 3p counter countP:" + countP);
		MsgObject msgObject = new MsgObject();
		
		msgObject.setInfo(info);
		msgObject.setType(2);
		msgObject.setUdpPacket(packet);
		try
		{
			permissionEventDispatcher.recvPush(msgObject);
		}
		catch (Exception e)
		{
			// TODO Auto-generated catch block
			//e.printStackTrace();
			log.error("3p msg push error " + e );
		}
		
	}
	else if (event.equals("4m"))
	{
		++countM;
		log.debug("msg 4m counter countM:" + countM);
		
		MsgObject msgObject = new MsgObject();
		
		msgObject.setInfo(info);
		msgObject.setType(1);
		msgObject.setUdpPacket(packet);
		try
		{
			permissionEventDispatcher.recvPush(msgObject);
		}
		catch (Exception e)
		{
			// TODO Auto-generated catch block
			//e.printStackTrace();
			log.error("4m msg push error " + e );
		}
	}
	else
	{
		JSONObject format = dataJson.getJSONObject("format");

		/**由于事件处理性能受限(140包每秒),更改实现方式为:
		*  先将事件入队列,之后由指定线程处理事件上报
		*/
		try
		{
			++countA;
			log.debug("msg NOTIFY counter countA:" + countA);
			eventDispatcher.recvPush(info);
		}
		catch (Exception e)
		{
			// TODO Auto-generated catch block
			//e.printStackTrace();
			log.error("NOTIFY msg push error " + e );
		}
		
		}

		
	}
	
}
3p和4m的消息类型放在一个队列。用type区分
public class MsgObject
{
    private int type ;
    private String info;
    private DatagramPacket udpPacket;
}


两个消息类型分发消息实现:

private class PushDispatcher extends Thread {
private boolean isDone = false;

public void shutdown() {
	isDone = true;
}

public PushDispatcher() {
	this.setDaemon(true);
	log.track(LoggerI.SYSDEBUG,"SDK event PushDispatcher start ");
}

@Override
public void run() {
	while (!isDone) {
		MsgObject msgObject = eventCache.msgFetchPush();
		
		
		/**处理接收到的事件推送*/
		
		if(1 == msgObject.getType())
		{
			//do your things
		}
		else if (2 == msgObject.getType())
		{
			//do your things
		}
	}
	log.track(LoggerI.SYSDEBUG,"SDK event PushDispatcher offline ");
}
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值