来源:http://hancool.blog.51cto.com/1836252/1352228

事情的缘由

因上级公司的信息化主管部门经常被投诉说是各种业务应用系统反映系统使用慢的问题,而都把问题归结于网速不给力。而业务系统一部份是总公司一级部署的,其它很多都是各个业务部门各自为政建设的,不知道从哪里找来的各种小公司,搞的五法八门的技术路线,没得统一标准、技术平台,所以水平就参差不齐。人少的时候还好点,业务和使用人一多,系统慢得象蜗牛。而网络基础设施这几年来改造、提升得差不多了,都是百兆桌面、千兆骨干了。地市级公司内部虽然办公点分散,但都是使用电力专用光纤建设的千兆骨干的MPLSVPN技术,地市公司与网省公司是千兆或万兆专用光纤。因此其实网络基础设施还是绰绰有余。为了自证清白,上级主管部门就盟生了建一个分层分布式的网速测试系统的想法。你说网速慢,那你在客户端上打开网页,测试一下各级网速,就可能看看到底是网速慢,还是应用系统本身太垃圾。

思路

在网络上给出的参考方法,WEB版的大部份是客户端用JAVASCRIPT下载一个大文件,然后根据速度=总下载量/时间,得到网速;专业的开源测试工具是iperf,是c版本的,和业余的相比,专业的不只一点点。于是,了解了一下iperf的基本思路和方法,于是采用JAVA来写,利用socket直接实现通信,服务端和客户端配合,通过TCP通信的数据量和使用时间来计算网络速度,一方面效率高、减少其它因素(如HTTP协议、JAVASCRIPT加载与执行效率等)的影响;另一方面,利用applet可以实现B/S应用,客户端部署使用简单。程序代码参考了OSCHINA的JGroups项目的JPerf.java。项目名称为jperf,使用eclipse开发和测试,目前实现了基本功能(因目前只是进行验证,因此未进行完整的异常处理、验证等)。

 import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.NumberFormat;
/***
* Tool to measure TCP throughput, similar to iperf
* @author Bela Ban
* @version $Id: JPerf.java,v 1.4 2007/12/28 23:29:17 belaban Exp $
*/
public class jperf implements Runnable{
boolean client;
boolean direction;//test direction:true-up test,false-down
int num;
InetAddress local_addr;
int local_port;
int remote_port;
InetAddress remote_addr;
int size;
int receivebuf=200000;
int sendbuf=200000;
static NumberFormat f;
Socket client_sock; static {
f=NumberFormat.getNumberInstance();
f.setGroupingUsed(false);
f.setMaximumFractionDigits(2);
} public jperf(){
} //实现Thread类的接口Runnable, 用于支持服务端连接的多线程
@Override
public void run() {
// TODO Auto-generated method stub
try {
server_accept_data();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
//用于applet和GUI调用
public jperf(String remote_addr,int remote_port,int num,int size,boolean direction) throws UnknownHostException{ this.remote_addr=InetAddress.getByName(remote_addr);
this.remote_port=remote_port;
this.num=num;
this.size=size;
this.direction=direction;
} private void start(boolean client, boolean direction,int num, int size, String local_addr, int local_port,
String remote_addr, int remote_port,int receivebuf, int sendbuf) throws IOException, ClassNotFoundException {
this.client=client;
this.direction=direction;
this.num=num;
this.size=size;
this.local_addr=InetAddress.getByName(local_addr);
this.local_port=local_port;
this.remote_addr=InetAddress.getByName(remote_addr);
this.remote_port=remote_port;
this.receivebuf=receivebuf;
this.sendbuf=sendbuf; if(client) {
client();
}
else {
server();
}
}
//客户端调用
public String client() throws IOException{ System.out.println("-- creating socket to " + this.remote_addr + ":" + this.remote_port);
client_sock=new Socket(this.remote_addr, remote_port); String result="";
if(sendExchangeData()==true){
if(direction==true) result=sendData(num,size);
else result=receiveData(num,size);
}
else{
result="connect to server and exchange data fail!";
}
System.out.println(result);
client_sock.close(); return result;
}
//客户端向服务端发送测试 的数据参数
private boolean sendExchangeData() throws IOException{
boolean ret=true; client_sock.setReceiveBufferSize(receivebuf);
client_sock.setSendBufferSize(sendbuf);
ObjectOutputStream write=new ObjectOutputStream(new BufferedOutputStream(client_sock.getOutputStream()));
write.writeObject(num);
write.flush();
write.writeObject(size);
write.flush();
write.writeObject(direction);
write.flush(); return ret;
}
//服务端调用
private void server() throws IOException, ClassNotFoundException
{
ServerSocket srv_sock=new ServerSocket(local_port, 10, this.local_addr);
System.out.println("-- waiting for client on " + srv_sock.getLocalSocketAddress());
while(true){
//wait for a client connect
Socket client_sock=srv_sock.accept();
//start a new thread deal this connection:
jperf thread_client=new jperf();
thread_client.client_sock=client_sock;
thread_client.sendbuf=sendbuf;
thread_client.receivebuf=receivebuf;
//每一个客户端单独一个线程,支持多个客户端同时连接
Thread thread=new Thread(thread_client);
thread.start();
} }
//服务器接收和发送测试 数据
private void server_accept_data() throws IOException, ClassNotFoundException{
client_sock.setReceiveBufferSize(receivebuf);
client_sock.setSendBufferSize(sendbuf);
System.out.println("-- accepted data connection from " + client_sock.getRemoteSocketAddress());
ObjectInputStream in=new ObjectInputStream(new BufferedInputStream(client_sock.getInputStream())); int num=0,size=0;
boolean direction=false;
num=(Integer)in.readObject();
size=(Integer)in.readObject();
direction=(Boolean)in.readObject(); if(num>0 && size>0) {
String result;
if(direction==true) result=receiveData(num,size);
else result=sendData(num,size); System.out.println(result);
}
else{
System.out.println("-- invalid exchange data! ");
}
client_sock.close();
}
//发送数据,并计算测试结果
private String sendData(int num,int size) throws IOException
{
System.out.println("-- sending data to "+client_sock.getRemoteSocketAddress().toString()+ " total "+num + " messages");
DataOutputStream out=new DataOutputStream(new BufferedOutputStream(client_sock.getOutputStream()));
byte[] buf=new byte[size];
for(int i=0;i<buf.length;i++) buf[i]=(byte)(i%128);
long start=0, stop;
int cnt=1;
int incr=num/10;
start=System.currentTimeMillis();
for(int i=0; i < num; i++) {
out.write(buf, 0, buf.length);
out.flush();
if(cnt % incr == 0)
System.out.println("-- sent " + cnt + " messages");
cnt++;
}
stop=System.currentTimeMillis();
long diff=stop-start;
String result=report("发送报文至 "+client_sock.getRemoteSocketAddress().toString(),(long)num*(long)size,diff); return result;
} //接收数据,并计算测试结果
private String receiveData(int num,int size) throws IOException{
System.out.println("-- accepted data from " + client_sock.getRemoteSocketAddress().toString()+" total "+num+" messages");
DataInputStream in=new DataInputStream(new BufferedInputStream(client_sock.getInputStream()));
byte[] buf=new byte[size];
long counter=0;
int incr=num/10;
long start=0, stop;
while(true) {
int len=in.read(buf, 0, buf.length);
if(len<=0) break;
if(start == 0)
start=System.currentTimeMillis();
counter+=len;
if((counter/size) % incr == 0)
System.out.println("-- received " + counter/size);
}
stop=System.currentTimeMillis();
long diff=stop-start;
String result=report("接收报文来自 "+client_sock.getRemoteSocketAddress().toString(),counter,diff); return result;
}
//计算测试结果
private String report(String direction,long totalbyte, double diff)
{
StringBuilder sb=new StringBuilder();
double tbs=totalbyte/(1024*1024);
if(tbs<1000) sb.append("\n"+direction+",测试数据总数" + f.format(tbs) + "Mbyte"+" ,用时 " + diff + "毫秒 ");
else{
tbs=tbs/1024;
sb.append("\n"+direction+",测试数据总数" + f.format(tbs)+ "Gbyte"+" ,用时 " + diff + "毫秒 ");
}
//tcp throughput:
double throughput=totalbyte / (diff / 1000.0) / 1024.0;
if(throughput < 1000)
sb.append("\n网络吞吐量: " + f.format(throughput) + "KB/秒");
else {
throughput/=1024.0;
sb.append("\n网络吞吐量: " + f.format(throughput) + "MB/秒");
}
//bandwidth
double bandwidth=totalbyte / (diff / 1000.0) / 1024.0*8;
if(bandwidth < 1000){
sb.append("\n网络带宽: " + f.format(bandwidth) + "Kb/秒");
}
else {
bandwidth/=1024.0;
if(bandwidth>1000){
bandwidth/=1024;
sb.append("\n网络带宽: " + f.format(bandwidth) + "Gb/秒");
}
else sb.append("\n网络带宽: " + f.format(bandwidth) + "Mb/秒");
}
return sb.toString();
}
static void help() {
System.out.println("JPerf [-help] [-client] [-direction <up|down>] [-num <number of msgs] [-size <bytes>] [-local_addr <interface>] [-local_port <port]" +
"[-remote_addr <IP addr>] [-remote_port <port>] [-receivebuf <bytes>] [-sendbuf <bytes>]");
}
//主程序执行入口
public static void main(String[] args) throws UnknownHostException {
boolean client=false;
boolean direction=false;//test direction:true-up test,false-down test
int num=10000;
int size=8192;
String local_addr=InetAddress.getLocalHost().getHostAddress();
String remote_addr=local_addr;
int local_port=5000;
int remote_port=5000;
int receivebuf=200000, sendbuf=200000;
for(int i=0; i < args.length; i++) {
if(args[i].equals("-client")) {
client=true;
continue;
}
if(args[i].equals("-num")) {
num=Integer.parseInt(args[++i]);
continue;
}
if(args[i].equals("-size")) {
size=Integer.parseInt(args[++i]);
continue;
}
if(args[i].equals("-local_addr")) {
local_addr=args[++i];
continue;
}
if(args[i].equals("-remote_addr")) {
remote_addr=args[++i];
continue;
}
if(args[i].equals("-local_port")) {
local_port=Integer.parseInt(args[++i]);
continue;
}
if(args[i].equals("-remote_port")) {
remote_port=Integer.parseInt(args[++i]);
continue;
}
if(args[i].equals("-receivebuf")) {
receivebuf=Integer.parseInt(args[++i]);
continue;
}
if(args[i].equals("-sendbuf")) {
sendbuf=Integer.parseInt(args[++i]);
continue;
}
if(args[i].equals("-direction")) {
String value=args[++i];
if(value.toLowerCase().equals("up")) direction=true;
else direction=false; continue;
}
help();
return;
}
try {
new jperf().start(client, direction,num, size, local_addr, local_port, remote_addr, remote_port, receivebuf, sendbuf);
}
catch(IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

编译代码:javac jperf.java

在服务端执行:java jperf,启动后默认在5000端口上进行监听。

在客户端执行:java jperf -client -remote_addr x.x.x.x,默认参数为数据报文数10000,数据包大小8192(针对默认的WINDOWS系统的TCP窗口),端口5000,方向为测试下行。

Java jperf -client -remote_addr x.x.x.x -direction up测试上行。

经过测试,两台通过百兆口交换机连接的计算机,吞吐量为11.3MB/s,带宽为90.4Mb/s左右。

本文出自 “一个业余程序员的历程” 博客,请务必保留此出处http://hancool.blog.51cto.com/1836252/1352228

在线网络速度测试JAVA程序(一):思路和控制台主程序【转】的更多相关文章

  1. 编写Java程序,实现从控制台输入对应个数的整数,输出对输入整数的从大到小显示

    编写Java程序,实现从控制台输入对应个数的整数,输出对输入整数的从大到小显示 效果如下: 实现代码: import java.util.Arrays; import java.util.Scanne ...

  2. 在线HTTP速度测试(响应时间测试)及浏览器兼容测试

    一.前言 网站的响应时间,是判断一个网站是否是好网站的重要的因素之一.百度首页的响应时间在全国各个省份小于10ms.这个响应时间远远好于竞争对手.根据美丽说的技术负责人分析,美丽说访问速度提升10%, ...

  3. 测试Java程序执行耗费的时间

    package test; public class Main { public static void main(String[] args) { long start = System.curre ...

  4. linux下开发板网络速度测试记录

        由于做的项目对于网络和USB的读写速度有很高的要求,因此新拿回来的板子要测试网络和usb的最佳传输速度.要考虑不少因素,先把我能想到的记录下来.     测试的环境是开发板和ubuntu虚拟机 ...

  5. 更准确的测试Java程序性能——JMH基准测试

    什么是JMH ​ JMH,即Java Microbenchmark Harness,Java平台下的一套微基准测试工具.如果我们需要测试API性能的话,就可以用上这个工具,所以它并不是取代单元测试的. ...

  6. Java程序通过代理访问网络

    问题背景 最近工作上有开发爬虫的任务,对目标网站数据进行抓取,由于大部分网站都在国外,无法直接访问,需要通过代理才能登录.爬虫部署的服务器在香港,所以爬虫部署到服务器后,是可以访问目标网站的,但本地开 ...

  7. 在Linux下通过rpm打包发布Java程序

    这个东西涉及的内容较多,根据下面这些文章慢慢学习 一个简单的例子 http://blog.csdn.net/king_on/article/details/7169384 按照文章中的步骤来,打包之后 ...

  8. Jmeter与LoadRunner 测试Java项目的坑

    32位的JDK,Jmeter.bat 最大内存只能配置1G,测不了大并发,所以用Jmeter测试时一定要改成64位的Jmeter用LR测试java程序的时候必须用32位的JDK 环境变量 在path的 ...

  9. 第一次java程序测试感受

    第一次JAVA程序设计测试,检验了一个暑假的成果.显而易见,我做的并不是很好,程序最起码的输入输出以及方法的定义还是没有问题的,但是考到了文件输入输出便看出来了.对于文件的输入输出,虽然我预习到那里, ...

随机推荐

  1. 面向连接的Socket Server的简单实现(简明易懂)

    一.基本原理 有时候我们需要实现一个公共的模块,需要对多个其他的模块提供服务,最常用的方式就是实现一个Socket Server,接受客户的请求,并返回给客户结果. 这经常涉及到如果管理多个连接及如何 ...

  2. 多态-I(继承实现)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  3. Java Proxy

    Client---->Interface A --        -- 代理类     Class AImpl 代理类是动态生成的,借助Proxy类和InvocationHandler接口进行实 ...

  4. 锋利的jQuery之事件

    jQuery中的事件和动画 JavaScript和HTML之间的交互是通过用户和浏览器操作页面时引发的事件来处理的.当文档或者它的某些元素发生某些变化或操作时,浏览器会自动生成一个事件.例如:当浏览器 ...

  5. 锋利的jquery学习笔记

    1.$("#tt")获取的永远都是一个jquery对象,所以要判断页面上是否存在某个对象不能像js中 if($("#tt")){ } 而是通过: ){ } ps ...

  6. Azure Automation:存储帐户之间blob拷贝

    在两个存储帐户之间进行blob拷贝,在客户端,使用Azue PowerShell脚本, 用存储帐户上下文(New-AzureStorageContext)来获取某个StorageAccount中的Co ...

  7. matlab自带princomp(PCA降维方式)

    matlab 中自带的函数就不必怀疑. princomp:principal componet analysis (PCA). [COEFF,SCORE,latent,tsquare]=princom ...

  8. ME23N PO 打印预览 打印问题

    ME23N进入PO订单,点message查看订单打印的配置 点message查看订单打印的配置 然后spro查看 选择相应的outputtype,然后双击processing routines 可以看 ...

  9. spring-mvc不拦截静态资源的配置

    spring-mvc不拦截静态资源的配置 标签: spring 2015-03-27 23:54 11587人阅读 评论(0) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许不得转载. &qu ...

  10. leetcode 125. Valid Palindrome ----- java

    Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignori ...