1 import java.io.*;
2 import java.net.InetAddress;
3 import java.net.ServerSocket;
4 import java.net.Socket;
5 import java.net.UnknownHostException;
6 import java.text.NumberFormat;
7 /***
8 * Tool to measure TCP throughput, similar to iperf
9 * @author Bela Ban
10 * @version $Id: JPerf.java,v 1.4 2007/12/28 23:29:17 belaban Exp $
11 */
12 public class jperf implements Runnable{
13 boolean client;
14 boolean direction;//test direction:true-up test,false-down
15 int num;
16 InetAddress local_addr;
17 int local_port;
18 int remote_port;
19 InetAddress remote_addr;
20 int size;
21 int receivebuf=200000;
22 int sendbuf=200000;
23 static NumberFormat f;
24 Socket client_sock;
25
26 static {
27 f=NumberFormat.getNumberInstance();
28 f.setGroupingUsed(false);
29 f.setMaximumFractionDigits(2);
30 }
31
32 public jperf(){
33 }
34
35 //实现Thread类的接口Runnable, 用于支持服务端连接的多线程
36 @Override
37 public void run() {
38 // TODO Auto-generated method stub
39 try {
40 server_accept_data();
41 } catch (IOException e) {
42 // TODO Auto-generated catch block
43 e.printStackTrace();
44 } catch (ClassNotFoundException e) {
45 // TODO Auto-generated catch block
46 e.printStackTrace();
47 }
48
49 }
50 //用于applet和GUI调用
51 public jperf(String remote_addr,int remote_port,int num,int size,boolean direction) throws UnknownHostException{
52
53 this.remote_addr=InetAddress.getByName(remote_addr);
54 this.remote_port=remote_port;
55 this.num=num;
56 this.size=size;
57 this.direction=direction;
58 }
59
60 private void start(boolean client, boolean direction,int num, int size, String local_addr, int local_port,
61 String remote_addr, int remote_port,int receivebuf, int sendbuf) throws IOException, ClassNotFoundException {
62 this.client=client;
63 this.direction=direction;
64 this.num=num;
65 this.size=size;
66 this.local_addr=InetAddress.getByName(local_addr);
67 this.local_port=local_port;
68 this.remote_addr=InetAddress.getByName(remote_addr);
69 this.remote_port=remote_port;
70 this.receivebuf=receivebuf;
71 this.sendbuf=sendbuf;
72
73 if(client) {
74 client();
75 }
76 else {
77 server();
78 }
79 }
80 //客户端调用
81 public String client() throws IOException{
82
83 System.out.println("-- creating socket to " + this.remote_addr + ":" + this.remote_port);
84 client_sock=new Socket(this.remote_addr, remote_port);
85
86 String result="";
87 if(sendExchangeData()==true){
88 if(direction==true) result=sendData(num,size);
89 else result=receiveData(num,size);
90 }
91 else{
92 result="connect to server and exchange data fail!";
93 }
94 System.out.println(result);
95 client_sock.close();
96
97 return result;
98 }
99 //客户端向服务端发送测试 的数据参数
100 private boolean sendExchangeData() throws IOException{
101 boolean ret=true;
102
103 client_sock.setReceiveBufferSize(receivebuf);
104 client_sock.setSendBufferSize(sendbuf);
105 ObjectOutputStream write=new ObjectOutputStream(new BufferedOutputStream(client_sock.getOutputStream()));
106 write.writeObject(num);
107 write.flush();
108 write.writeObject(size);
109 write.flush();
110 write.writeObject(direction);
111 write.flush();
112
113 return ret;
114 }
115 //服务端调用
116 private void server() throws IOException, ClassNotFoundException
117 {
118 ServerSocket srv_sock=new ServerSocket(local_port, 10, this.local_addr);
119 System.out.println("-- waiting for client on " + srv_sock.getLocalSocketAddress());
120 while(true){
121 //wait for a client connect
122 Socket client_sock=srv_sock.accept();
123 //start a new thread deal this connection:
124 jperf thread_client=new jperf();
125 thread_client.client_sock=client_sock;
126 thread_client.sendbuf=sendbuf;
127 thread_client.receivebuf=receivebuf;
128 //每一个客户端单独一个线程,支持多个客户端同时连接
129 Thread thread=new Thread(thread_client);
130 thread.start();
131 }
132
133 }
134 //服务器接收和发送测试 数据
135 private void server_accept_data() throws IOException, ClassNotFoundException{
136 client_sock.setReceiveBufferSize(receivebuf);
137 client_sock.setSendBufferSize(sendbuf);
138 System.out.println("-- accepted data connection from " + client_sock.getRemoteSocketAddress());
139 ObjectInputStream in=new ObjectInputStream(new BufferedInputStream(client_sock.getInputStream()));
140
141 int num=0,size=0;
142 boolean direction=false;
143 num=(Integer)in.readObject();
144 size=(Integer)in.readObject();
145 direction=(Boolean)in.readObject();
146
147 if(num>0 && size>0) {
148 String result;
149 if(direction==true) result=receiveData(num,size);
150 else result=sendData(num,size);
151
152 System.out.println(result);
153 }
154 else{
155 System.out.println("-- invalid exchange data! ");
156 }
157 client_sock.close();
158 }
159 //发送数据,并计算测试结果
160 private String sendData(int num,int size) throws IOException
161 {
162 System.out.println("-- sending data to "+client_sock.getRemoteSocketAddress().toString()+ " total "+num + " messages");
163 DataOutputStream out=new DataOutputStream(new BufferedOutputStream(client_sock.getOutputStream()));
164 byte[] buf=new byte[size];
165 for(int i=0;i<buf.length;i++) buf[i]=(byte)(i%128);
166 long start=0, stop;
167 int cnt=1;
168 int incr=num/10;
169 start=System.currentTimeMillis();
170 for(int i=0; i < num; i++) {
171 out.write(buf, 0, buf.length);
172 out.flush();
173 if(cnt % incr == 0)
174 System.out.println("-- sent " + cnt + " messages");
175 cnt++;
176 }
177 stop=System.currentTimeMillis();
178 long diff=stop-start;
179 String result=report("发送报文至 "+client_sock.getRemoteSocketAddress().toString(),(long)num*(long)size,diff);
180
181 return result;
182 }
183
184 //接收数据,并计算测试结果
185 private String receiveData(int num,int size) throws IOException{
186 System.out.println("-- accepted data from " + client_sock.getRemoteSocketAddress().toString()+" total "+num+" messages");
187 DataInputStream in=new DataInputStream(new BufferedInputStream(client_sock.getInputStream()));
188 byte[] buf=new byte[size];
189 long counter=0;
190 int incr=num/10;
191 long start=0, stop;
192 while(true) {
193 int len=in.read(buf, 0, buf.length);
194 if(len<=0) break;
195 if(start == 0)
196 start=System.currentTimeMillis();
197 counter+=len;
198 if((counter/size) % incr == 0)
199 System.out.println("-- received " + counter/size);
200 }
201 stop=System.currentTimeMillis();
202 long diff=stop-start;
203 String result=report("接收报文来自 "+client_sock.getRemoteSocketAddress().toString(),counter,diff);
204
205 return result;
206 }
207 //计算测试结果
208 private String report(String direction,long totalbyte, double diff)
209 {
210 StringBuilder sb=new StringBuilder();
211 double tbs=totalbyte/(1024*1024);
212 if(tbs<1000) sb.append("\n"+direction+",测试数据总数" + f.format(tbs) + "Mbyte"+" ,用时 " + diff + "毫秒 ");
213 else{
214 tbs=tbs/1024;
215 sb.append("\n"+direction+",测试数据总数" + f.format(tbs)+ "Gbyte"+" ,用时 " + diff + "毫秒 ");
216 }
217 //tcp throughput:
218 double throughput=totalbyte / (diff / 1000.0) / 1024.0;
219 if(throughput < 1000)
220 sb.append("\n网络吞吐量: " + f.format(throughput) + "KB/秒");
221 else {
222 throughput/=1024.0;
223 sb.append("\n网络吞吐量: " + f.format(throughput) + "MB/秒");
224 }
225 //bandwidth
226 double bandwidth=totalbyte / (diff / 1000.0) / 1024.0*8;
227 if(bandwidth < 1000){
228 sb.append("\n网络带宽: " + f.format(bandwidth) + "Kb/秒");
229 }
230 else {
231 bandwidth/=1024.0;
232 if(bandwidth>1000){
233 bandwidth/=1024;
234 sb.append("\n网络带宽: " + f.format(bandwidth) + "Gb/秒");
235 }
236 else sb.append("\n网络带宽: " + f.format(bandwidth) + "Mb/秒");
237 }
238 return sb.toString();
239 }
240 static void help() {
241 System.out.println("JPerf [-help] [-client] [-direction <up|down>] [-num <number of msgs] [-size <bytes>] [-local_addr <interface>] [-local_port <port]" +
242 "[-remote_addr <IP addr>] [-remote_port <port>] [-receivebuf <bytes>] [-sendbuf <bytes>]");
243 }
244 //主程序执行入口
245 public static void main(String[] args) throws UnknownHostException {
246 boolean client=false;
247 boolean direction=false;//test direction:true-up test,false-down test
248 int num=10000;
249 int size=8192;
250 String local_addr=InetAddress.getLocalHost().getHostAddress();
251 String remote_addr=local_addr;
252 int local_port=5000;
253 int remote_port=5000;
254 int receivebuf=200000, sendbuf=200000;
255 for(int i=0; i < args.length; i++) {
256 if(args[i].equals("-client")) {
257 client=true;
258 continue;
259 }
260 if(args[i].equals("-num")) {
261 num=Integer.parseInt(args[++i]);
262 continue;
263 }
264 if(args[i].equals("-size")) {
265 size=Integer.parseInt(args[++i]);
266 continue;
267 }
268 if(args[i].equals("-local_addr")) {
269 local_addr=args[++i];
270 continue;
271 }
272 if(args[i].equals("-remote_addr")) {
273 remote_addr=args[++i];
274 continue;
275 }
276 if(args[i].equals("-local_port")) {
277 local_port=Integer.parseInt(args[++i]);
278 continue;
279 }
280 if(args[i].equals("-remote_port")) {
281 remote_port=Integer.parseInt(args[++i]);
282 continue;
283 }
284 if(args[i].equals("-receivebuf")) {
285 receivebuf=Integer.parseInt(args[++i]);
286 continue;
287 }
288 if(args[i].equals("-sendbuf")) {
289 sendbuf=Integer.parseInt(args[++i]);
290 continue;
291 }
292 if(args[i].equals("-direction")) {
293 String value=args[++i];
294 if(value.toLowerCase().equals("up")) direction=true;
295 else direction=false;
296
297 continue;
298 }
299 help();
300 return;
301 }
302 try {
303 new jperf().start(client, direction,num, size, local_addr, local_port, remote_addr, remote_port, receivebuf, sendbuf);
304 }
305 catch(IOException e) {
306 e.printStackTrace();
307 } catch (ClassNotFoundException e) {
308 e.printStackTrace();
309 }
310 }
311 }