【多文件自平衡云传输 完结】网速监控

接上篇【多文件自平衡云传输 五】可视化界面---显示进度条在做好了界面之后,再实现一个可以监控传输速率的功能。能够将速率动态地显示在界面上。

需要显示什么格式?

介于网络传输都是以字节(B)为单位的。但是如果此刻传输的数据很大时这个值为很大,效果就不好。所以第一步需要一个能将字节(B)转换为KB,MB,GB,而且可以自己指定中/英文格式的工具。这个工具只做一件事,就是转换单位获取带单位的字符串。

比如:678---->678B,    1024--->1.00KB。具体代码如下:

public class TimeDate {
    public static final int CHAR_CN = 1;        //标记:表示中文格式
    public static final int CHAR_EN = 0;	//标记:表示英文格式
    
    //两种格式对应的显示  英文:B        中文:字节
    private static final String[] charTypes = { "B", "字节" };    
	
    /**
     * 一个int型4字节(32位)java中写一个整数,默认是int型:比如1,就是默认为int型。
     * 一个long型8字节(64位)Java中整数后边显式地带上L 就表示long型
     * 所以此处一定要显式的带上L
     */
    private static final long[] level = { 
        1L << 10,	//1KB
        1L << 20,	//1MB
        1L << 30,	//1GB
        1L << 40,	//1TB
    };
    private static final char[] un = {
	'K',
	'M',
	'G',
	'T',
    };
	
    public static String sizeToByte(long size) {
	return sizeToByte(size, CHAR_EN);
    }
	
    //我的目的是传过来一个文件片段大小,我可以将其转换单位。而且可以指定显示格式(中/英)
    public static String sizeToByte(long size, int charType) {
	String type = charTypes[charType];
		
        if (size < 0L) {
	    return "非法长度值!";
	}
		
	//0 - 999B的情况
	if (size < level[0]) {
	    return size + type;
	}
		
	StringBuffer res = new StringBuffer();
		
	//1KB - 999KB的情况
	if (size < level[1]) {
	    return toBytes(size, 0, res, type);
	}
	//1MB - 999MB的情况
	if (size < level[2]) {
	    return toBytes(size, 1, res, type);
	}
	//1GB - 999GB的情况
	if (size < level[3]) {
	    return toBytes(size, 2, res, type);
	}
		
	//1TB以上的情况---这种情况基本上现在还不存在
	return toBytes(size, 3, res, type);
    }
	
    //单位换算核心方法---传递过来的size的单位永远是B
    private static String toBytes(long size, int index, StringBuffer res, String type) {
        double tmp = (double) size / (double) level[index];
		
	/**
	 * 通过上述计算得出的tmp是double类型的,也就是说永远是包含小数点的,再换句话说就是永远可以保证含最低一位小数
	 * 只不过分两种情况:
	 * 1.	小数位数大于两位
	 * 2.	小数位数小于等于两位。比如:999.0
	 * 所以我要截取小数点后两位就需要补个0
	 */
	String s = String.valueOf(tmp) + "0";
	int dotIndex = s.indexOf('.');
		
	//截取小数点后两位。保证精度
	res.append(s.substring(0, dotIndex + 3));
		
	//添加单位
	res.append(un[index]).append(type);
        return res.toString();
    }
	
}

传输速率 = 传输长度 / 时间

传输长度在最最最之前就封装好了。无论是一个文件片段的长度还是一个文件的长度都可以获取到,现在只要求出时间差就行了。打算给两个显示:平均速率 和 当前速率。

首先速率的计算要在每次接收完一个片段之后就计算一次。

当前速率:传输完一个文件片段的速率。获取上下两个片段传输的时间差除以当前接收片段。

平均速率:每次传输完之后的时刻 - 最开始传输的时刻。就可以表示从开始到接收到现在用了多少时间,当然需要记录这个段内的传输总长度。

基于上述分析,具体实现如下:

定义接口,两个方法不仅可以测试接收的速率还可以测试发送的速率。

public interface IFileSectionSendReceiveSpeed {
    void afterSend(int len);
    void afterReceive(int len);
}
public class FileSectionSendReceiveSpeedAdapter implements IFileSectionSendReceiveSpeed {

    public FileSectionSendReceiveSpeedAdapter() {}

    @Override
    public void afterSend(int len) {}

    @Override
    public void afterReceive(int len) {}

}
public class NetSpeed extends FileSectionSendReceiveSpeedAdapter {
    private volatile static NetSpeed me;
    private volatile static long startReceiveTime;		//资源接收前计时
    private volatile static long lastReceiveTime;		//接收完一个片段计时
    private volatile static long receiveSize;		//当前接收总长度
    private volatile static long curSpeed;			//当前速度
    private volatile static long averSpeed;	                //平均速度
	
    private NetSpeed() {}
		
    public static NetSpeed getInstance() {
	if(me == null) {
	    synchronized (NetSpeed.class) {
	        if(me == null) {
		    long time = System.currentTimeMillis();
		    startReceiveTime = time;
		    lastReceiveTime = time ;
		    me = new NetSpeed();
		}
	    }
	}
	return me;
    }

    @Override
    public  void afterReceive(int len) {
	long curTime = System.currentTimeMillis();
	/**
	 * 求出与上次时间差。注意一定要是双精度的,要不然如果是整数,在时间差很短的情况下deltaTime值为0
	 * 会抛出除0错异常
	 */
	double deltaTime = curTime - lastReceiveTime;
		
	//总计耗时---用于计算总速度
	long allTime = curTime - startReceiveTime;
		
        //系统时间单位为毫秒--将其转换为秒。求出单位时间内接收的片段长度
	curSpeed = (long) (len*1000.0 / deltaTime);
		
	//更新当前接收长度
	receiveSize = receiveSize += len;
		
	//计算平均速率
	averSpeed = (long) (receiveSize *1000.0 / allTime);
		
	//更新上次接收片段时间
	lastReceiveTime = curTime;
    }

    public static long getAverSpeed() {
	return averSpeed;
    }
	
    public static long getCurSpeed() {
	return curSpeed;
    }
	
    public static void clear() {
        me = null;
	receiveSize = 0;
	curSpeed = averSpeed = 0;
	startReceiveTime = lastReceiveTime = 0;
    }
}

然后在接收完一个片段之后计算速度

public class FileSectionSendRecevice {
    private ISendReceive sendReceive;
    private IFileSectionSendReceiveSpeed speed;
	
    public FileSectionSendRecevice() {
	this.sendReceive = new NetSendReceive();
	speed = new FileSectionSendReceiveSpeedAdapter();
    }
    
    public void setSpeed(IFileSectionSendReceiveSpeed speed) {
	this.speed = speed;
    }
    
    //....

    public FileSectionInfo receiveSection(DataInputStream dis) throws IOException {
	byte[] bytes = this.sendReceive.receive(dis, 16);
	FileSectionInfo sectionInfo = new FileSectionInfo(bytes);
		
	int len;
	if((len = sectionInfo.getLen()) > 0) {
	    byte[] content = this.sendReceive.receive(dis, len);
	    sectionInfo.setContent(content);
            
            //此处进行测速
	    this.speed.afterReceive(len);
	}
	return sectionInfo;
    }
    
    //...
}

为了能让其显示在界面上,还需要对界面内容做一些调整:

public abstract class ReceiveProgressDialog extends JDialog implements IMecView {
    //...
    private JLabel jlblCurrentSpeed;
    private JLabel jlblAverageSpeed;
    

    @Override
    public void init() {
        //...		
        JPanel jpnlFooter = new JPanel(new GridLayout(1, 2));
	this.add(jpnlFooter, BorderLayout.SOUTH);
		
	JPanel jpnlCurrentSpeed = new JPanel(new FlowLayout(FlowLayout.LEFT));
	jpnlFooter.add(jpnlCurrentSpeed);
		
	JLabel jlblCurrentSpeedTopic = new JLabel("当前速率 : ");
	jlblCurrentSpeedTopic.setFont(smallFont);
	jpnlCurrentSpeed.add(jlblCurrentSpeedTopic);
		
	this.jlblCurrentSpeed = new JLabel(TimeDate.sizeToByte(0L, TimeDate.CHAR_CN));
	this.jlblCurrentSpeed.setFont(smallFont);
	jpnlCurrentSpeed.add(this.jlblCurrentSpeed);
		
	JPanel jpnlAverageSpeed = new JPanel(new FlowLayout(FlowLayout.LEFT));
	jpnlFooter.add(jpnlAverageSpeed);
		
	JLabel jlblAverageSpeedTopic = new JLabel("平均速率 : ");
	jlblAverageSpeedTopic.setFont(smallFont);
	jpnlAverageSpeed.add(jlblAverageSpeedTopic);
		
	this.jlblAverageSpeed = new JLabel(TimeDate.sizeToByte(0L, TimeDate.CHAR_CN));
	this.jlblAverageSpeed.setFont(smallFont);
	jpnlAverageSpeed.add(this.jlblAverageSpeed);
    }

    public  void updataSpeed(long allSize, long curSize) {
	jlblAverageSpeed.setText(TimeDate.sizeToByte(allSize, TimeDate.CHAR_CN));
	jlblCurrentSpeed.setText(TimeDate.sizeToByte(curSize, TimeDate.CHAR_CN));
    }
    
    //....
}

接收时启动计时,线程安全的单例模式下可保证只初始化计时一次。然后再更新一下界面的速率显示即可。

测试结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenWrt是一个开源的路由器操作系统,它提供了丰富的功能和灵活的定制选项。通过引用中提到的基于OpenWrt的软路由搭建,你可以进行网速监控。 在OpenWrt上进行网速监控可以使用check_mk来实现。首先,你需要确保check_mk监听端口已经启动。你可以通过在终端输入命令"netstat -an | grep 6556"来检查端口是否处于监听状态,如引用所示。 接下来,你需要在OpenWrt上配置check_mk的xinetd服务。你可以通过编辑"/etc/xinetd.d/mk"文件来新增check_mk的配置,如引用所示。在配置文件中,你可以设置监听的端口号(默认是6556),以及其他一些参数。 配置完成后,你需要重启xinetd服务,使配置生效。然后,你可以使用check_mk来监控和收集OpenWrt的网速数据。 请注意,这只是一个示例配置,具体的配置可能会因为网络环境和需求的不同而有所变化。你可以根据自己的实际情况进行调整和定制。 总结起来,通过在OpenWrt上配置check_mk的监听端口和xinetd服务,你可以实现对网速监控。希望这对你有帮助。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [群晖openwrt旁路由_[openwrt监控]如何配置Check MK进行基于openwrt的软路由监控](https://blog.csdn.net/weixin_39637397/article/details/110198114)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值