Dav*_*vid 6 java sockets networking nio file-transfer
我有两台无线电脑连接到N无线路由器.这些PC中的每一台都以108-150Mbps的速度连接.
从理论上讲,我应该能够在绝对最佳条件下以13.5MB/s的速度传输到18.75MB/s.
第一台计算机(即发送)使用非常快的SSD,如果我没记错的话,大约100MB/s.CPU使用率也低于20%.
它在656367ms发送了1960273535字节(1.8GB).那是2.8MB/s(108兆比特中的22个).当我打开任务管理器时,我发现只有25-27%的网络连接被使用.
我正在寻找可以使传输更快(通过网络)的任何想法,建议或改进.我想在一个线程上从磁盘缓冲文件并从另一个线程发送缓冲数据,但我不确定这是不是一个好主意.这是SSCCE:
主办:
import java.io.*;
import java.net.*;
public class Host {
public static void main(String[] args) throws IOException {
ServerSocket servsock = new ServerSocket(15064);
Socket sock = servsock.accept();
long time = System.currentTimeMillis();
OutputStream out = sock.getOutputStream();
FileInputStream fileInputStream = new FileInputStream("C:\\complete.rar");
byte [] buffer = new byte[64*1024];
int bytesRead = 0;
long totalSent = 0;
while ( (bytesRead = fileInputStream.read(buffer)) != -1)
{
if (bytesRead > 0)
{
out.write(buffer, 0, bytesRead);
totalSent += bytesRead;
System.out.println("sent " + totalSent);
}
}
sock.close();
System.out.println("Sent " + totalSent + " bytes in "
+ (System.currentTimeMillis() - time) + "ms.");
}
}
Run Code Online (Sandbox Code Playgroud)
客户:
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws Exception {
Socket sock = new Socket("127.0.0.1", 15064);
InputStream in = sock.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream("output.rar");
byte [] buffer = new byte[64*1024];
int bytesRead = 0;
while ( (bytesRead = in.read(buffer)) != -1)
fileOutputStream.write(buffer, 0, bytesRead);
sock.close();
fileOutputStream.close();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我尝试映射网络驱动器并通过它发送文件,Windows更糟糕 - 2.35MB/s.根据这篇文章http://tinyurl.com/634qaqg映射网络驱动器比FTP快,我也没有时间继续玩游戏并设置FTP服务器.
编辑2:更改计时器后,结果是通过WiFi以3MB/s的速度传输.我讨厌"理论"吞吐量.当我买东西时,我想知道它的真实表现.事实证明,代码确实受到WiFi速度的限制.我仍然愿意接受建议.
编辑3:在100Mbps LAN上运行程序后,它设法以11.8MB/s的速度传输文件.考虑到最大传输速率为12.5MB/s,这非常好.
在2.8MB/s时,缓慢与代码无关.几乎可以肯定,由于无线网络无法实现理论吞吐量(可能是由于环境条件).
很容易测试是否是这种情况:只需在同一台计算机之间进行大型ftp或scp文件传输,并查看您所看到的吞吐量类型.
我建议你尝试下面打印的代码
Wed Oct 26 14:21:03 BST 2011: Accepted a connection
Wed Oct 26 14:21:13 BST 2011: Transfer rate was 3212.5 MB/s
Run Code Online (Sandbox Code Playgroud)
在服务器上和客户端打印
Wed Oct 26 14:21:03 BST 2011 Sending for 10.0 seconds.
Wed Oct 26 14:21:13 BST 2011 ... sent.
Wed Oct 26 14:21:13 BST 2011 ... received 33691287552
Send and received 3212.8 MB/s
Run Code Online (Sandbox Code Playgroud)
注意:传输的总金额是双倍,因为客户端发送到服务器的所有内容都是服务器发送到客户端.
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Date;
public class EchoServerMain {
public static void main(String... args) throws IOException {
int port = args.length < 1 ? 55555 : Integer.parseInt(args[0]);
ServerSocketChannel ss = ServerSocketChannel.open();
ss.socket().bind(new InetSocketAddress(port));
while (!ss.socket().isClosed()) {
SocketChannel s = ss.accept();
System.out.println(new Date() + ": Accepted a connection");
long start = System.nanoTime();
ByteBuffer bytes = ByteBuffer.allocateDirect(32*1024);
int len;
long total = 0;
// Thank you @EJP, for a more elegant single loop.
while ((len = s.read(bytes)) >= 0 || bytes.position() > 0) {
bytes.flip();
s.write(bytes);
bytes.compact();
total += len;
}
long time = System.nanoTime() - start;
System.out.printf(new Date() + ": Transfer rate was %.1f MB/s%n", total * 1e9 / 1024 / 1024 / time);
}
ss.close();
}
}
Run Code Online (Sandbox Code Playgroud)
和
import java.io.EOFException;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Date;
public class EchoClientMain {
public static void main(String ... args) throws IOException {
String hostname = args.length < 1 ? "localhost" : args[0];
int port = args.length < 2 ? 55555 : Integer.parseInt(args[1]);
double seconds = args.length < 3 ? 10 : Double.parseDouble(args[2]);
SocketChannel s = SocketChannel.open(new InetSocketAddress(hostname, port));
s.configureBlocking(false);
ByteBuffer bytes = ByteBuffer.allocateDirect(32*1024);
System.out.printf(new Date()+ " Sending for %.1f seconds.%n", seconds);
long start = System.nanoTime();
long dataSent = 0, dataReceived = 0;
// run for 10 seconds.
while(start + seconds*1e9 > System.nanoTime()) {
bytes.clear();
int wlen = s.write(bytes);
if (wlen < 0) throw new IOException();
dataSent += wlen;
bytes.clear();
int rlen = s.read(bytes);
if (rlen < 0) throw new EOFException();
dataReceived += rlen;
}
System.out.println(new Date()+ " ... sent.");
while(dataReceived < dataSent) {
bytes.clear();
int rlen = s.read(bytes);
if (rlen < 0) throw new EOFException();
dataReceived += rlen;
}
s.close();
long time = System.nanoTime() - start;
System.out.println(new Date()+ " ... received "+dataReceived);
System.out.printf("Send and received %.1f MB/s%n", dataReceived * 1e9/1024/1024/time);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10240 次 |
| 最近记录: |