[英]Error while sending large files through socket
I'm trying to send large files via socket. 我正在尝试通过套接字发送大文件。 The program works fine for small files (such as html pages or pdf), but when i send files over 3/4 mb the output is always corrupted (viewing it with a text editor i noticed that the last few lines are always missing).
该程序适用于较小的文件(例如html页面或pdf),但是当我发送超过3/4 mb的文件时,输出始终会损坏(使用文本编辑器查看它时,我注意到最后几行始终会丢失)。
Here's the code of the server: 这是服务器的代码:
BufferedInputStream in = null;
FileOutputStream fout = null;
try {
server = new ServerSocket(port);
sock = server.accept();
in = new BufferedInputStream(sock.getInputStream());
setPerc(0);
received = 0;
int incByte = -1;
fout = new FileOutputStream(path+name, true);
long size = length;
do{
int buffSize;
if(size >= 4096){
buffSize = 4096;
}else{
buffSize = 1;
}
byte[] o = new byte[buffSize];
incByte = in.read(o, 0, buffSize);
fout.write(o);
received+=buffSize;
setPerc(calcPerc(received, length));
size -= buffSize;
//d("BYTE LETTI => "+incByte);
}while(size > 0);
server.close();
} catch (IOException e) {
e("Errore nella ricezione file: "+e);
}finally{
try {
fout.flush();
fout.close();
in.close();
} catch (IOException e) {
e("ERRORE INCOMINGFILE");
}
}
pr.release(port);
And here's the code of the client: 这是客户端的代码:
FileInputStream fin = null;
BufferedOutputStream out = null;
try {
sock = new Socket(host, port);
fin = new FileInputStream(file);
out = new BufferedOutputStream(sock.getOutputStream());
long size = file.length();
int read = -1;
do{
int buffSize = 0;
if(size >= 4096){
buffSize = 4096;
}else{
buffSize = (int)size;
}
byte[] o = new byte[buffSize];
for(int i = 0; i<o.length;i++){
o[i] = (byte)0;
}
read = fin.read(o, 0, buffSize);
out.write(o);
size -= buffSize;
//d("BYTE LETTI DAL FILE => "+read);
}while(size > 0);
} catch (UnknownHostException e) {
} catch (IOException e) {
d("ERRORE NELL'INVIO DEL FILE: "+e);
e.printStackTrace();
}finally{
try {
out.flush();
out.close();
fin.close();
} catch (IOException e) {
d("Errore nella chiusura dei socket invio");
}
}
i think it's something related with the buffer size, but i can't figure out what's wrong here. 我认为这与缓冲区大小有关,但我无法弄清这里出了什么问题。
This is incorrect: 这是不正确的:
byte[] o = new byte[buffSize];
incByte = in.read(o, 0, buffSize);
fout.write(o);
You are reading up to buffSize
bytes and then writing exactly buffSize
bytes. 您正在阅读最多
buffSize
字节,然后写准确 buffSize
字节。
You are doing the same thing at the other end as well. 您在另一端也正在做相同的事情。
You may be able to get away with this when reading from a file 1 , but when you read from a socket then a read
is liable to give you a partially filled buffer, especially if the writing end can't always keep ahead of the reading end 'cos you are hammering the network with a large transfer. 您可以从文件中读取1时逃脱。但是,当你从一个套接字读那么
read
容易给你一个部分填充缓冲,特别是如果写到底能不能始终保持阅读的未来最终,因为您正在通过大量传输来锤击网络。
The right way to do it is: 正确的方法是:
incByte = in.read(o, 0, buffSize);
fout.write(o, 0, incByte);
1 - It has been observed that when you read from a local file, a read
call will typically give you all of the bytes that you requested (subject to the file size, etc). 1-已经观察到,当您从本地文件
read
, read
调用通常会为您提供所请求的所有字节(取决于文件大小等)。 So, if you set buffSize
to the length of the file, this code would probably work when reading from a local file. 因此,如果将
buffSize
设置为文件的长度,则从本地文件读取该代码可能会起作用。 But doing this is a bad idea, because you are relying behaviour that is not guaranteed by either Java or a typical operating system. 但这是一个坏主意,因为您所依赖的行为是Java或典型操作系统无法保证的。
You might have a problem eg here. 您可能在这里遇到问题。
read = fin.read(o, 0, buffSize);
out.write(o);
Here read gives you the count of bytes you've actually just read. 在这里, read提供了您实际上刚刚读取的字节数。 On the next line you should write out only as many bytes as you've read.
在下一行,您应该只写出已读取的字节数。
In other words, you cannot expect the size of the file you're reading to be multiple of your buffer size. 换句话说,您不能期望正在读取的文件的大小是缓冲区大小的倍数。
Review your server code too for the same issue. 同样,请检查您的服务器代码。
The correct way to copy streams in Java is as follows: 在Java中复制流的正确方法如下:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
where count
is an int,
and buffer
is a byte[]
array of length > 0, typically 8k. 其中
count
是一个int,
buffer
是一个长度大于0(通常为8k)的byte[]
数组。 You don't need to allocate byte arrays inside the loop, and you don't need a byte array of a specific size. 您不需要在循环内分配字节数组,也不需要特定大小的字节数组。 Specifically, it's a complete waste of space to allocate a buffer as large as the file;
具体地说,分配与文件一样大的缓冲区完全浪费了空间。 it only works up to files of
Integer.MAX_VALUE
bytes, and it doesn't scale. 它仅适用于
Integer.MAX_VALUE
字节的文件,并且无法缩放。
You do need to save the count returned by 'read()' and use it in the 'write()' method as shown above. 您确实需要保存“ read()”返回的计数,并在“ write()”方法中使用它,如上所示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.