来源: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. Python OpenCV ——Matplotlib显示图片

    Color image loaded by OpenCV is in BGR mode.But Matplotlib displays in RGB mode.So color images will ...

  2. HTML的表单

    HTML表单 <!-- <form></form>标签对用来创建一个表单,即定义表单的开始和结束位置,<form>表单具有下面等属性 1.action属性用来 ...

  3. 【LEETCODE OJ】Candy

    Problem link: http://oj.leetcode.com/problems/candy/ Suppose we are given an array R[1..N] that are ...

  4. mac上安装MySQL

    mysql 官网下载http://dev.mysql.com/downloads/mysql/ 注意安装mysql-5.5.17-osx10.6-x86_64.dmg这样安装方便设置系统安全权限后 点 ...

  5. HTTP消息头

    (一)初识HTTP消息头 但凡搞WEB开发的人都离不开HTTP(超文本传输协议),而要了解HTTP,除了HTML本身以外,还有一部分不可忽视的就是HTTP消息头.做过Socket编程的人都知道,当我们 ...

  6. 解决div里插入img下边缝隙问题

    <html>   <head>   <title> new document </title>   <meta name="author ...

  7. magento设置订单状态

    <?php require_once('app/Mage.php');umask(0);Mage::app('default'); $order = Mage::getModel('sales/ ...

  8. 前端学习资源(CSS+HTML5)

    CSS CSS | MDN CSS参考手册 CSS探索之旅 Web前端实验室 STYLESHEETS CSS3中的content字符编码 Font Awesome, 一套绝佳的图标字体库和CSS框架 ...

  9. MyBatis对应的xml的数据类型

    MyBatis对应的xml的数据类型 JDBC Type Java TypeCHAR StringVARCHAR StringLONGVARCHAR StringNUMERIC java.math.B ...

  10. Windows 10下Chrome不能启动的问题

    不能启动了 Chrome突然不能启动了,点击图标也没反应,打开任务管理器,发现点击图标后,Google Ghrome短暂地出现,随即消失. 如何解决? 解决方案 打开安装目录: C:\Program ...