问题
I am writing a small java program that can measure the speed of my local network. It is the first time I am working with sockets but I've put together a program that works. The only problem is that the measurements are far from accurate (way too low).
This is the server code:
ServerSocket servsock = new ServerSocket(13267);
while (true) {
System.out.println("Waiting...");
Socket sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
File myFile = new File("test.txt");
FileInputStream in = new FileInputStream(myFile);
OutputStream out = sock.getOutputStream();
int bytes = 0;
byte[] buffer = new byte[8192];
int len;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
bytes += len;
}
System.out.println("Transfer completed, " + bytes + " bytes sent");
out.flush();
sock.close();
}
This is the client code:
Socket sock = new Socket("192.168.0.100", 13267);
System.out.println("Connecting to : " + sock);
InputStream in = sock.getInputStream();
FileOutputStream out = new FileOutputStream("received.txt");
int bytes = 0;
byte[] buffer = new byte[8192];
int len;
long start = System.currentTimeMillis();
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
bytes += len;
}
long end = System.currentTimeMillis();
out.close();
sock.close();
double kbps = (bytes / 1000) / ((end - start) / 1000);
System.out.println("Speed: " + kbps + " kbps");
Is this because I am working with my own buffers that slow everything down or what could be the problem? Tips & hints are welcome too.
回答1:
If you want to measure bandwidth you don't need to send a file, you can just send blank data. If the file isn't large enough, the cost of making the connection (typically 20 ms) will make your connection appear slow.
I suggest you send data for at least 2 to 10 seconds.
This article has sample code on the fastest way to transfer data over a socket. How fast are Java sockets
Using integer arithmetic to produce a floating point is likely to get errors.
double kbps = (bytes / 1000) / ((end - start) / 1000);
Say bytes
is 2100 and end - start
is 1900 you will get
double kbps = (2100 / 1000) / (1900 / 1000);
double kbps = 2 / 1; == 2.
is almost the same as (but with less error)
double kbps = bytes / (end - start);
better
double kbps = (double) bytes / (end - start);
To send blank data
byte[] bytes = new byte[8*1024];
OutputStream out = socket.getOutputStream();
// send data for given amount of time, e.g. 2000 ms
long endTime = System.currentTimeMS() + timeToSendDataMS;
do {
out.write(bytes);
} while(endTime > System.currentTimeMS());
To read blank data
long total = 0;
byte[] bytes = new byte[8*1024];
InputStream in = socket.getInputStream();
int len;
while((len = in.read(bytes)) != -1)
total += len;
回答2:
It's because you write to disk each 8K package that you receive on the client side.
FileOutputStream out = new FileOutputStream("received.txt");
...
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
...
}
This is not necessary for a speed test. Just reading the bytes into the buffer, is enough. Skip writing the packages to file in the client code.
Optionally, you could write the received packages into a ByteArrayOutputStream
. Java will handle the allocation itself in the JVM's heap space. And it will not biase the speed test.
回答3:
Your code is invalid. You're ending the timer at the wrong point. The transfer isn't complete until you have flushed or closed the output stream.
来源:https://stackoverflow.com/questions/6946104/java-network-file-transfer-problem