在 java /android 中提高 TCP 套接字的传输速度
Posted
技术标签:
【中文标题】在 java /android 中提高 TCP 套接字的传输速度【英文标题】:Increase transfer speed of TCP socket in java /android 【发布时间】:2013-04-17 11:48:36 【问题描述】:我正在开发基于 wifi direct 的文件传输应用程序。我可以看到使用 TCP 套接字的传输速度并不令人满意。速度通常为 1Mbps。每当我分析数据传输图时,我可以看到很多尖峰,而且很多秒根本没有数据传输。我知道传输速度应该更高(可能是 20-30Mbps) 请帮助我提高传输速度。 接受连接的serversocket是
private void serverTask()
Log.v(TAG, "server task");
try
serverRunning = true;
ServerSocket serverSocket = new ServerSocket(
DeviceDetailFragment.PORT);
serverSocket.setReceiveBufferSize(TCP_BUFFER_SIZE);
Socket client = serverSocket.accept();
BufferedInputStream inputstream = new BufferedInputStream(
client.getInputStream());
// new BufferedInputStream(client.getInputStream(), 8 * 1024);
BufferedReader bufferedStream = new BufferedReader(
new InputStreamReader(inputstream));
fileName = bufferedStream.readLine();
fileSizeInBytes = bufferedStream.readLine();
fileMime = bufferedStream.readLine();
f = new File(Globals.fileSavingLocation + fileName);
File dirs = new File(f.getParent());
if (!dirs.exists())
dirs.mkdirs();
if (f.exists())
f.delete();
f.createNewFile();
IOUtils.copy(inputstream, new FileOutputStream(f));
serverSocket.close();
isSuccessful = true;
catch (IOException e)
isSuccessful = false;
Log.e(TAG, e.getMessage());
serverRunning = false;
发送数据的客户端有如下代码:
private void clientTask(Intent intent)
String fileUri = intent.getExtras().getString(EXTRAS_FILE_PATH);
String host = intent.getExtras().getString(EXTRAS_ADDRESS);
String fileName = intent.getExtras().getString(FILE_NAME);
String fileMimeType = intent.getExtras().getString(FILE_MIME_TYPE);
final long sizeInBytes = intent.getExtras().getLong(FILE_SIZE);
Socket socket = new Socket();
int port = intent.getExtras().getInt(EXTRAS_PORT);
try
socket.setSendBufferSize(TCP_BUFFER_SIZE);
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)),
SOCKET_TIMEOUT);
BufferedOutputStream stream = new BufferedOutputStream(
socket.getOutputStream());
ContentResolver cr = FileTransferService.this
.getApplicationContext().getContentResolver();
InputStream is = null;
BufferedWriter bufferStream = new BufferedWriter(
new OutputStreamWriter(stream));
bufferStream.write(fileName);
bufferStream.newLine();
bufferStream.flush();
bufferStream.write(String.valueOf(sizeInBytes));
bufferStream.newLine();
bufferStream.flush();
bufferStream.write(fileMimeType);
bufferStream.newLine();
bufferStream.flush();
try
is = new BufferedInputStream(cr.openInputStream(Uri
.parse(fileUri)));
catch (FileNotFoundException e)
isSuccessful = false;
IOUtils.copy(is, stream);
isSuccessful = true;
catch (IOException e)
Log.e(TAG, e.getMessage());
isSuccessful = false;
finally
if (socket != null)
if (socket.isConnected())
try
socket.close();
catch (IOException e)
// Give up
e.printStackTrace();
TCP_BUFFER_SIZE
的值设置为1024*512
。
我尝试了很多改变 TCP_BUFFER_SIZE 的值,但没有成功。我用 Apache Commons IOUtils 替换了复制流的实现。 帮帮我
更新: 请看下面的传输图
【问题讨论】:
你真的需要如此频繁地刷新缓冲区吗,缓冲的全部意义在于减少系统调用/刷新的次数? 感谢您的评论。我已经删除了那些冲洗。但是,它并没有帮助我,因为它只是 2-3 个电话 【参考方案1】:您似乎正在超载缓冲区,来自setReceiveBufferSize() javadoc
随后可以通过调用来更改该值 Socket.setReceiveBufferSize(int)。但是,如果应用程序希望 允许接收窗口大于 64K 字节,由 RFC1323 定义 那么建议的值必须先在 ServerSocket 中设置 绑定到本地地址。这意味着,ServerSocket 必须是 使用无参数构造函数创建,然后 setReceiveBufferSize() 必须调用,最后将 ServerSocket 绑定到一个地址 调用 bind()。
【讨论】:
非常感谢您的指点。我根据您的建议更正了我的代码。现在速度为 2-3 Mbps,TCP_BUFFER_SIZE=1024*1024。但我相信,速度还可以快得多。我们将非常感谢您的进一步帮助。【参考方案2】:我会尝试使用普通 Socket 而不使用文件进行简单的数据传输。
有一个简单的服务器,在您连接时发送 100 MB 的空数据。让客户端尽可能快地读取该数据,并报告它获得的吞吐量。在同一台机器上,您应该很容易看到超过 100 MB/s 的速度。一旦这给出了一个好的数字,请在 android 客户端上尝试。
【讨论】:
以上是关于在 java /android 中提高 TCP 套接字的传输速度的主要内容,如果未能解决你的问题,请参考以下文章
Android调试注解处理器AnnotationProcessor