使用套接字传输大文件
当我使用套接字编程传输大文件时,收到的文件不完整,即它是一个 mp3 文件,当我播放时听起来很奇怪。 代码是:
服务器端:
File myFile = new File("abc.mp3");
{
Socket sock = servsock.accept();
int packetsize=1024;
double nosofpackets=Math.ceil(((int) myFile.length())/packetsize);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
for(double i=0;i<nosofpackets+1;i++) {
byte[] mybytearray = new byte[packetsize];
bis.read(mybytearray, 0, mybytearray.length);
System.out.println("Packet:"+(i+1));
OutputStream os = sock.getOutputStream();
os.write(mybytearray, 0,mybytearray.length);
os.flush();
}
}
客户端:
int packetsize=1024;
FileOutputStream fos = new FileOutputStream("zz.mp3");
BufferedOutputStream bos = new BufferedOutputStream(fos);
double nosofpackets=Math.ceil(((int) (new File("abc.mp3")).length())/packetsize);
for(double i=0;i<nosofpackets+1;i++)
{
InputStream is = sock.getInputStream();
byte[] mybytearray = new byte[packetsize];
int bytesRead = is.read(mybytearray, 0,mybytearray.length );
System.out.println("Packet:"+(i+1));
bos.write(mybytearray, 0,mybytearray.length);
}
sock.close();
bos.close();
在客户端,我使用了 new File("abc.mp3")).length
只是为了简单起见(我可以从服务器端发送文件的长度)。
如果客户端和服务器在同一台机器上,此代码可以完美运行,但如果它们位于不同的机器上,文件就会失真。
When I'm transferring a large file using socket programming, the received file is incomplete i.e. it is an mp3 file which when i play sounds weird.
The code is:
Server side:
File myFile = new File("abc.mp3");
{
Socket sock = servsock.accept();
int packetsize=1024;
double nosofpackets=Math.ceil(((int) myFile.length())/packetsize);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
for(double i=0;i<nosofpackets+1;i++) {
byte[] mybytearray = new byte[packetsize];
bis.read(mybytearray, 0, mybytearray.length);
System.out.println("Packet:"+(i+1));
OutputStream os = sock.getOutputStream();
os.write(mybytearray, 0,mybytearray.length);
os.flush();
}
}
Client side:
int packetsize=1024;
FileOutputStream fos = new FileOutputStream("zz.mp3");
BufferedOutputStream bos = new BufferedOutputStream(fos);
double nosofpackets=Math.ceil(((int) (new File("abc.mp3")).length())/packetsize);
for(double i=0;i<nosofpackets+1;i++)
{
InputStream is = sock.getInputStream();
byte[] mybytearray = new byte[packetsize];
int bytesRead = is.read(mybytearray, 0,mybytearray.length );
System.out.println("Packet:"+(i+1));
bos.write(mybytearray, 0,mybytearray.length);
}
sock.close();
bos.close();
On the Client side I have used new File("abc.mp3")).length
just for simplicity (I could send the length of the file from the server side).
This code works perfectly if client and server are the same machine, but the file gets distorted if they are on different machines.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在 Java 中复制流的规范方法:
适用于任何大于零的缓冲区大小。应极力避免将缓冲区大小与输入大小相关联。
The canonical way to copy a stream in Java:
Works with any buffer size greater than zero. The temptation to relate the buffer size to the input size should be strenuously avoided.
我认为问题在于您忽略了各种 read 调用返回的值,并假设它们完全填充了缓冲区。这是有问题的:
从文件读取时,最后读取可能不会填充缓冲区。
从套接字读取时,任何读取都可能在填充缓冲区之前返回。
您写入的最终结果会将垃圾放入流(在服务器端)和目标文件(在客户端)中。
此外,根据文件的大小将文件分成块是没有意义的。一直读到文件末尾。
I think that the problem is that you are ignoring the values returned by various
read
calls, and assuming they completely fill the buffer. This is problematic:When reading from a file, the last read probably won't fill the buffer.
When reading from a socket, any read may return before filling the buffer.
The net result that your writes will put junk into the stream (at the server end), and into the destination file (at the client end).
Furthermore, it is pointless dividing the file up into chunks based on the size of the file. Just read until you get to the end of file.
不要重新发明轮子,请使用
IOUtils。复制()
。Don't reinvent the wheel, use
IOUtils.copy()
.不要使用数据包。
尝试使用 ByteArrayOutputStream 而不是使用静态字节数组。
继续从输入流读取,直到到达 EOF。 n 将其中的每一个写入 ByteArrayOutputStream。
希望这有帮助。
Don't use packets.
Try using the ByteArrayOutputStream instead of using the static byte array.
keep reading from the inputstream until u reach EOF. n write each of this to the ByteArrayOutputStream.
Hope this helps.