Java network file transfer problem
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 accurat开发者_JAVA百科e (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.
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;
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.
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.
精彩评论