socket传送文件时总是丢失数据的问题 用socket写了一个客户端向服务端传送文件的小程序,但是传送过去的文件总是比客户端原来的文件小一些,导致传送过去的文件都不能用,请问这个会是什么原因导致的呢,这个是不是就是传送中丢包的情况呢 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 哈哈,又是楼主啊,还在弄socket传送文件的程序啊,帮你顶把 客户端代码:package com.ydz.client.socket;import java.io.*;import java.net.*;public class SocketClient { public static void main(String[] args) { Socket s = null; try{ File file = new File("F://java文档资料//api//html_zh_CN.zip"); //FileInputStream fis = new FileInputStream(file); DataInputStream fis = new DataInputStream(new FileInputStream(file)); long fileSize = fis.available(); String fileName = file.getName(); s = new Socket("127.0.0.1", 10000); System.out.println("已经连接上服务器"); DataOutputStream os = new DataOutputStream(s.getOutputStream()); PrintWriter pw = new PrintWriter(os, true); pw.println(fileSize); pw.println(fileName); //os = new BufferedOutputStream(os); byte[] buffer = new byte[1024]; int len = 0; while((len = fis.read(buffer, 0, 1024)) != -1){ os.write(buffer, 0, len); os.flush(); } os.close(); fis.close(); s.close(); } catch (IOException e){ e.printStackTrace(); } finally { try{ if(s != null) s.close(); } catch (IOException e) { e.printStackTrace(); } } }}服务端代码:package com.ydz.server.socket;import java.io.*;import java.net.*;import com.ydz.server.thread.inceptfile.InceptFileThread;public class SocketServer { public void start() { try{ ServerSocket ss = new ServerSocket(10000); System.out.println("等待客户端连接"); int i = 1; while(true){ Socket s = ss.accept(); System.out.println("第"+String.valueOf(i)+"客户端连接进来了"); InceptFileThread ifThread = new InceptFileThread(s, i); ifThread.start(); i++; } } catch (IOException e){ e.printStackTrace(); } } public static void main(String[] args) { SocketServer ss = new SocketServer(); ss.start(); }}服务端线程代码:package com.ydz.server.thread.inceptfile;import java.io.*;import java.net.Socket;public class InceptFileThread extends Thread { private Socket s; private int fileNumber; public InceptFileThread(Socket s, int fileNumber){ this.s = s; this.fileNumber = fileNumber; } public void run(){ try{ DataInputStream is = new DataInputStream(s.getInputStream()); BufferedReader br = new BufferedReader(new InputStreamReader(is)); System.out.println("第"+String.valueOf(fileNumber)+"个文件开始上传"); String fileSizeStr = br.readLine(); System.out.println("文件长度"+fileSizeStr); String fileName = br.readLine(); System.out.println("文件名称"+fileName); StringBuilder filePath = new StringBuilder(); filePath.append("E://主服务器//file") .append(fileNumber); File fileCatalog = new File(filePath.toString()); if(!fileCatalog.exists()) fileCatalog.mkdirs(); filePath.append("//").append(fileName); File file = new File(filePath.toString()); //FileOutputStream fos = new FileOutputStream(file); DataOutputStream fos = new DataOutputStream(new FileOutputStream(file)); byte[] buffer = new byte[1024]; System.out.println("开始接收文件"); int len = 0; while((len = is.read(buffer, 0, 1024)) != -1){ fos.write(buffer, 0, len); fos.flush(); } is.close(); fos.close(); System.out.println("文件"+fileNumber+"上传完毕"); } catch (IOException e) { e.printStackTrace(); } }} byte[] buffer = new byte[1024*5];数组改大点试试 1).将SocketClient类中的以下几行代码注释掉 PrintWriter pw = new PrintWriter(os, true); pw.println(fileSize); pw.println(fileName);2).将InceptFileThread类中以下几行代码注释掉String fileSizeStr = br.readLine();System.out.println("文件长度"+fileSizeStr);String fileName = br.readLine();System.out.println("文件名称"+fileName);3).将InceptFileThread其他用到文件名的地方自己再做相应调整即可! 用有缓冲功能的bufferoutputstream试一下把,应该不会是大小的问题嘿嘿,帮你顶。 用有缓冲功能的bufferoutputstream试一下把,应该不会是大小的问题嘿嘿,帮你顶。 感谢你一直关注我的帖子,不过BufferedOutputStream我已经试过了,真的不好用,效果和数组小的时候是一样的,把数组设大了可以正常。 呵呵,楼主,不好意思,昨天没有看帖子。你所说的“丢失数据的问题”:字符流的话一般用于读取字符、数字类型的文本,而字节流的话一般用于读取图片、还有就是你说的rar文件那些,所以上一个帖子的发送rar的时候会出现文件不完整那些,我想应该也是这原因吧。现在这个帖子,我刚刚试了一下,你改一下就可以了://服务端package test2;import java.io.*;import java.net.*;public class SocketServer { public void start() { try{ ServerSocket ss = new ServerSocket(10000); System.out.println("等待客户端连接"); int i = 1; while(true){ Socket s = ss.accept(); System.out.println("第"+String.valueOf(i)+"客户端连接进来了"); InceptFileThread ifThread = new InceptFileThread(s, i); ifThread.start(); i++; } } catch (IOException e){ e.printStackTrace(); } } public static void main(String[] args) { SocketServer ss = new SocketServer(); ss.start(); }}class InceptFileThread extends Thread { private Socket s; private int fileNumber; public InceptFileThread(Socket s, int fileNumber){ this.s = s; this.fileNumber = fileNumber; } public void run(){ try{ DataInputStream is = new DataInputStream(s.getInputStream()); //BufferedReader br = new BufferedReader(new InputStreamReader(is)); System.out.println("第"+String.valueOf(fileNumber)+"个文件开始上传"); String fileName = is.readUTF();//.readLine(); System.out.println("文件名称"+fileName); String fileSizeStr = is.readUTF();//.readLine(); System.out.println("文件长度"+fileSizeStr); StringBuilder filePath = new StringBuilder(); filePath.append("c://file") .append(fileNumber); File fileCatalog = new File(filePath.toString()); if(!fileCatalog.exists()) fileCatalog.mkdirs(); filePath.append("//").append(fileName); File file = new File(filePath.toString()); //FileOutputStream fos = new FileOutputStream(file); DataOutputStream fos = new DataOutputStream(new FileOutputStream(file)); byte[] buffer = new byte[1024]; System.out.println("开始接收文件"); int len = 0; while((len = is.read(buffer,0,1024)) != -1){ fos.write(buffer,0,1024); fos.flush(); } is.close(); fos.close(); System.out.println("文件"+fileNumber+"上传完毕"); } catch (IOException e) { e.printStackTrace(); } }}//客户端package test2;import java.io.*;import java.net.*;public class SocketClient { public static void main(String[] args) { Socket s = null; try{ File file = new File("c:/src.zip"); //FileInputStream fis = new FileInputStream(file); DataInputStream fis = new DataInputStream(new FileInputStream(file)); long fileSize = fis.available(); String fileName = file.getName(); s = new Socket("127.0.0.1", 10000); System.out.println("已经连接上服务器"); DataOutputStream os = new DataOutputStream(s.getOutputStream()); os.writeUTF(fileName); os.flush(); os.writeUTF(String.valueOf(fileSize)); os.flush();// PrintWriter pw = new PrintWriter(os, true);// pw.println(fileSize);// pw.flush();// pw.println(fileName);// pw.flush(); //os = new BufferedOutputStream(os); byte[] buffer = new byte[1024]; int len = 0; while((len = fis.read(buffer,0,1024)) != -1){ os.write(buffer,0,1024); os.flush(); } os.close(); fis.close(); s.close(); } catch (IOException e){ e.printStackTrace(); } finally { try{ if(s != null) s.close(); } catch (IOException e) { e.printStackTrace(); } } }} long fileSize = fis.available(); 你为什么不用file.length() 问题出在BufferedReader的readLine上,当调用readLine时,BufferedReader在第一次会试图把自己的buffer读满,默认size是8192个字节,以后每次调用readLine时,如果buffer没有耗尽的话,继续从buffer来读。这样分析一下就可以知道为啥lz说“传送过去的文件总是比客户端原来的文件小”。当开始读取文件名和文件大小时,实际上BufferedReader已经读了8192个字节了,然后以后每次用DataInputStream读时,其实已经是从8193开始读的,那么bytes【文件名+文件大小】至8192间的字节是没有被DataInputStream读取的,也就是少了8192-bytes【文件名+文件大小】这么多字节。至于为什么修改byte[] buffer = new byte[1024*5];可以我没有想明白请教了一下,应该是用DataStream的read/writeUTF来实现你要传的字符串。如下:/** * desc: * XXX<br> * ---------------------------------------------------------------------------- * ver. date who what * ---------------------------------------------------------------------------- * 0.0.1 2010-5-24 leisore add * ---------------------------------------------------------------------------- */package cn.leisore.daily._2010_05_24;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.PrintWriter;import java.net.Socket;/** * DataTrans * * @author leisore * @since version 0.0.1 */public class SocketClient { public static void main(String[] args) { Socket s = null; try { File file = new File("c:/jndi-1_4_2-tutorial.zip"); // FileInputStream fis = new FileInputStream(file); DataInputStream fis = new DataInputStream(new FileInputStream(file)); long fileSize = fis.available(); String fileName = file.getName(); s = new Socket("127.0.0.1", 10002); System.out.println("已经连接上服务器"); DataOutputStream os = new DataOutputStream(s.getOutputStream()); os.writeUTF(String.valueOf(fileSize)); os.writeUTF(fileName); // os = new BufferedOutputStream(os); byte[] buffer = new byte[1024]; int count = 0; int len = 0; while ((len = fis.read(buffer, 0, 1024)) != -1) { os.write(buffer, 0, len); os.flush(); } os.close(); fis.close(); s.close(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (s != null) s.close(); } catch (IOException e) { e.printStackTrace(); } } }}/** * desc: * XXX<br> * ---------------------------------------------------------------------------- * ver. date who what * ---------------------------------------------------------------------------- * 0.0.1 2010-5-24 leisore add * ---------------------------------------------------------------------------- */package cn.leisore.daily._2010_05_24;import java.io.DataInputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.net.ServerSocket;import java.net.Socket;/** * SocketServer * * @author leisore * @since version 0.0.1 */public class SocketServer { public void start() { try { ServerSocket ss = new ServerSocket(10002); // System.out.println("等待客户端连接"); int i = 1; while (true) { Socket s = ss.accept(); // System.out.println("第" + String.valueOf(i) + "客户端连接进来了"); InceptFileThread ifThread = new InceptFileThread(s, i); ifThread.start(); i++; } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { SocketServer ss = new SocketServer(); ss.start(); }}class InceptFileThread extends Thread { private Socket s; private int fileNumber; public InceptFileThread(Socket s, int fileNumber) { this.s = s; this.fileNumber = fileNumber; } public void run() { try { DataInputStream dis = new DataInputStream(s.getInputStream()); System.out.println("第" + String.valueOf(fileNumber) + "个文件开始上传"); String fileSizeStr = dis.readUTF(); System.out.println("文件长度" + fileSizeStr); String fileName = dis.readUTF(); System.out.println("文件名称" + fileName); StringBuilder filePath = new StringBuilder(); filePath.append("E:/").append(fileNumber); File fileCatalog = new File(filePath.toString()); if (!fileCatalog.exists()) fileCatalog.mkdirs(); filePath.append("//").append(fileName); File file = new File(filePath.toString()); FileOutputStream fos = new FileOutputStream(file); byte[] buffer = new byte[1024]; System.out.println("开始接收文件"); int len = 0; int count = 0; while ((len = dis.read(buffer, 0, 1024)) != -1) { fos.write(buffer, 0, len); fos.flush(); } fos.close(); System.out.println("文件" + fileNumber + "上传完毕"); } catch (IOException e) { e.printStackTrace(); } }}应该是好使的。 liuzhengkang leisore感谢二位朋友的关注,问题应该就在这里了,leisore朋友分析的很有道理,但是现在我还有一点不明白,为什么我以前的写法中,把byte数组的长度改大(我改成了1M个字节的长度),为什么就能上传完整的文件呢,按照leisore朋友的分析,就是改到多大也应该是不对的,而且我测试中,如果btye数组长度是1024时,测试上传的所有文件大小都是差1024*16个字节的。 按照leisore朋友的分析,确实把数据丢失在那了一部分,但是按照我以前的写法,把byte数组长度调大,确实也可以正常接收文件了,就是不明白这个地方到底是为什么。 与byte数组长度的大小没关系啊,你按照我上面的程序跑了吗?不管上传的文件有多大都没问题啊。 自己来写通讯框架,太麻烦了,使用apache mina,通信层自己就不用管了,专心写好你的业务逻辑就行了 客户端代码:Java codeFile file = new File("F://java文档资料//api//html_zh_CN.zip"); //FileInputStream fis = new FileInputStream(file); DataInputStream fis = new DataInputStream(new FileInputStream(file)); long fileSize = fis.available(); String fileName = file.getName(); s = new Socket("127.0.0.1", 10000); System.out.println("已经连接上服务器"); DataOutputStream os = new DataOutputStream(s.getOutputStream()); PrintWriter pw = new PrintWriter(os, true);============================================================================================你传的文件是 rar,即二进制文件你用的输出是XXXWriter,Writer是用来写文本的,即字符流,这么做必然丢数据。你把传输的文件换成文本文件应该就没问题了,要么把XXXWriter换成操作字节的输出者。 选用的类有问题。楼主要弄清楚,到底是要传输文件,还是要传输文件的内容。如果只传输文件的内容,就要杜绝文件大小等信息的传输。Socket通信,底层采用TCP协议,不会出现丢包现象。ObjectOutputStream,这个类,是用来传输可序列化的对象,File对象不可被序列化吧 ?如果楼主非要将文件的名称和大小传输到对方,那就要自己定义一个简单点的协议。(或者说,传输数据的数据格式)然后,收发双方遵照协议,即可。楼主的程序,有两大败笔。首先,数据的发送方式,前后不一致。 前面两个数据以对象的形式进行发送,后面的文件内容,采用二进制byte数组形式发送。 根据编程理念来将,可以通篇使用ObjectOutputStream发送信息,byte数组也可以看作可序列化的对象。其次,数据的接收方面,在数据格式 前后不一致的情况下 前者采用的缓冲区进行处理。 这是一个致命的错误。为什么呢 ? 前面读入的数据,从缓冲区里面读取。后面的数据没有从同一缓冲区里面读取。 会造成缓冲区里面会驻留一些缓冲数据无法被程序读取出来。 JDBC 请问JAVA定时器怎么写? 多个tcp连接接收数据,写入xml问题请教???? SuppressWarnings 注解除了用unchecked,还可以用哪些值。 最简单的一个小问题~ jexcelapi处理Excel的问题!......急! java截取第n对括号内的字符 打印分页,预览怎样才能实现呀! 如何用JAVA实现语音聊天? 可以在自定义的类中,预先使用该类作为成员函数的类型吗? 急.!求教关于StringBuffer的.高手们指点下吧 请大家帮忙
import java.net.*;public class SocketClient { public static void main(String[] args)
{
Socket s = null;
try{
File file = new File("F://java文档资料//api//html_zh_CN.zip");
//FileInputStream fis = new FileInputStream(file);
DataInputStream fis = new DataInputStream(new FileInputStream(file));
long fileSize = fis.available();
String fileName = file.getName();
s = new Socket("127.0.0.1", 10000);
System.out.println("已经连接上服务器");
DataOutputStream os = new DataOutputStream(s.getOutputStream());
PrintWriter pw = new PrintWriter(os, true);
pw.println(fileSize);
pw.println(fileName);
//os = new BufferedOutputStream(os);
byte[] buffer = new byte[1024];
int len = 0;
while((len = fis.read(buffer, 0, 1024)) != -1){
os.write(buffer, 0, len);
os.flush();
}
os.close();
fis.close();
s.close();
} catch (IOException e){
e.printStackTrace();
} finally {
try{
if(s != null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}服务端代码:package com.ydz.server.socket;import java.io.*;
import java.net.*;import com.ydz.server.thread.inceptfile.InceptFileThread;public class SocketServer { public void start()
{
try{
ServerSocket ss = new ServerSocket(10000);
System.out.println("等待客户端连接");
int i = 1;
while(true){
Socket s = ss.accept();
System.out.println("第"+String.valueOf(i)+"客户端连接进来了");
InceptFileThread ifThread = new InceptFileThread(s, i);
ifThread.start();
i++;
}
} catch (IOException e){
e.printStackTrace();
}
}
public static void main(String[] args)
{
SocketServer ss = new SocketServer();
ss.start();
}
}
服务端线程代码:package com.ydz.server.thread.inceptfile;import java.io.*;
import java.net.Socket;public class InceptFileThread extends Thread { private Socket s;
private int fileNumber;
public InceptFileThread(Socket s, int fileNumber){
this.s = s;
this.fileNumber = fileNumber;
}
public void run(){
try{
DataInputStream is = new DataInputStream(s.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
System.out.println("第"+String.valueOf(fileNumber)+"个文件开始上传");
String fileSizeStr = br.readLine();
System.out.println("文件长度"+fileSizeStr);
String fileName = br.readLine();
System.out.println("文件名称"+fileName);
StringBuilder filePath = new StringBuilder();
filePath.append("E://主服务器//file")
.append(fileNumber);
File fileCatalog = new File(filePath.toString());
if(!fileCatalog.exists())
fileCatalog.mkdirs();
filePath.append("//").append(fileName);
File file = new File(filePath.toString());
//FileOutputStream fos = new FileOutputStream(file);
DataOutputStream fos = new DataOutputStream(new FileOutputStream(file));
byte[] buffer = new byte[1024];
System.out.println("开始接收文件");
int len = 0;
while((len = is.read(buffer, 0, 1024)) != -1){
fos.write(buffer, 0, len);
fos.flush();
}
is.close();
fos.close();
System.out.println("文件"+fileNumber+"上传完毕");
} catch (IOException e) {
e.printStackTrace();
}
}
}
数组改大点试试
pw.println(fileSize);
pw.println(fileName);
2).将InceptFileThread类中以下几行代码注释掉String fileSizeStr = br.readLine();
System.out.println("文件长度"+fileSizeStr);
String fileName = br.readLine();
System.out.println("文件名称"+fileName);
3).将InceptFileThread其他用到文件名的地方自己再做相应调整即可!
你所说的“丢失数据的问题”:
字符流的话一般用于读取字符、数字类型的文本,
而字节流的话一般用于读取图片、还有就是你说的rar文件那些,所以上一个帖子的发送rar的时候会出现文件不完整那些,我想应该也是这原因吧。
现在这个帖子,我刚刚试了一下,你改一下就可以了://服务端
package test2;import java.io.*;
import java.net.*;
public class SocketServer { public void start()
{
try{
ServerSocket ss = new ServerSocket(10000);
System.out.println("等待客户端连接");
int i = 1;
while(true){
Socket s = ss.accept();
System.out.println("第"+String.valueOf(i)+"客户端连接进来了");
InceptFileThread ifThread = new InceptFileThread(s, i);
ifThread.start();
i++;
}
} catch (IOException e){
e.printStackTrace();
}
}
public static void main(String[] args)
{
SocketServer ss = new SocketServer();
ss.start();
}
}class InceptFileThread extends Thread { private Socket s;
private int fileNumber;
public InceptFileThread(Socket s, int fileNumber){
this.s = s;
this.fileNumber = fileNumber;
}
public void run(){
try{
DataInputStream is = new DataInputStream(s.getInputStream());
//BufferedReader br = new BufferedReader(new InputStreamReader(is));
System.out.println("第"+String.valueOf(fileNumber)+"个文件开始上传");
String fileName = is.readUTF();//.readLine();
System.out.println("文件名称"+fileName);
String fileSizeStr = is.readUTF();//.readLine();
System.out.println("文件长度"+fileSizeStr);
StringBuilder filePath = new StringBuilder();
filePath.append("c://file")
.append(fileNumber);
File fileCatalog = new File(filePath.toString());
if(!fileCatalog.exists())
fileCatalog.mkdirs();
filePath.append("//").append(fileName);
File file = new File(filePath.toString());
//FileOutputStream fos = new FileOutputStream(file);
DataOutputStream fos = new DataOutputStream(new FileOutputStream(file));
byte[] buffer = new byte[1024];
System.out.println("开始接收文件");
int len = 0;
while((len = is.read(buffer,0,1024)) != -1){
fos.write(buffer,0,1024);
fos.flush();
}
is.close();
fos.close();
System.out.println("文件"+fileNumber+"上传完毕");
} catch (IOException e) {
e.printStackTrace();
}
}
}
//客户端
package test2;import java.io.*;
import java.net.*;public class SocketClient { public static void main(String[] args)
{
Socket s = null;
try{
File file = new File("c:/src.zip");
//FileInputStream fis = new FileInputStream(file);
DataInputStream fis = new DataInputStream(new FileInputStream(file));
long fileSize = fis.available();
String fileName = file.getName();
s = new Socket("127.0.0.1", 10000);
System.out.println("已经连接上服务器");
DataOutputStream os = new DataOutputStream(s.getOutputStream());
os.writeUTF(fileName);
os.flush();
os.writeUTF(String.valueOf(fileSize));
os.flush();
// PrintWriter pw = new PrintWriter(os, true);
// pw.println(fileSize);
// pw.flush();
// pw.println(fileName);
// pw.flush();
//os = new BufferedOutputStream(os);
byte[] buffer = new byte[1024];
int len = 0;
while((len = fis.read(buffer,0,1024)) != -1){
os.write(buffer,0,1024);
os.flush();
}
os.close();
fis.close();
s.close();
} catch (IOException e){
e.printStackTrace();
} finally {
try{
if(s != null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
至于为什么修改byte[] buffer = new byte[1024*5];可以我没有想明白
请教了一下,应该是用DataStream的read/writeUTF来实现你要传的字符串。如下:
/**
* desc:
* XXX<br>
* ----------------------------------------------------------------------------
* ver. date who what
* ----------------------------------------------------------------------------
* 0.0.1 2010-5-24 leisore add
* ----------------------------------------------------------------------------
*/
package cn.leisore.daily._2010_05_24;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;/**
* DataTrans
*
* @author leisore
* @since version 0.0.1
*/
public class SocketClient { public static void main(String[] args) {
Socket s = null;
try {
File file = new File("c:/jndi-1_4_2-tutorial.zip");
// FileInputStream fis = new FileInputStream(file);
DataInputStream fis = new DataInputStream(new FileInputStream(file));
long fileSize = fis.available();
String fileName = file.getName();
s = new Socket("127.0.0.1", 10002);
System.out.println("已经连接上服务器");
DataOutputStream os = new DataOutputStream(s.getOutputStream());
os.writeUTF(String.valueOf(fileSize));
os.writeUTF(fileName);
// os = new BufferedOutputStream(os);
byte[] buffer = new byte[1024]; int count = 0;
int len = 0;
while ((len = fis.read(buffer, 0, 1024)) != -1) {
os.write(buffer, 0, len);
os.flush();
}
os.close();
fis.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (s != null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* desc:
* XXX<br>
* ----------------------------------------------------------------------------
* ver. date who what
* ----------------------------------------------------------------------------
* 0.0.1 2010-5-24 leisore add
* ----------------------------------------------------------------------------
*/
package cn.leisore.daily._2010_05_24;import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;/**
* SocketServer
*
* @author leisore
* @since version 0.0.1
*/
public class SocketServer {
public void start() {
try {
ServerSocket ss = new ServerSocket(10002);
// System.out.println("等待客户端连接");
int i = 1;
while (true) {
Socket s = ss.accept();
// System.out.println("第" + String.valueOf(i) + "客户端连接进来了");
InceptFileThread ifThread = new InceptFileThread(s, i);
ifThread.start();
i++;
}
} catch (IOException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
SocketServer ss = new SocketServer();
ss.start();
}
}class InceptFileThread extends Thread { private Socket s;
private int fileNumber; public InceptFileThread(Socket s, int fileNumber) {
this.s = s;
this.fileNumber = fileNumber;
} public void run() {
try { DataInputStream dis = new DataInputStream(s.getInputStream());
System.out.println("第" + String.valueOf(fileNumber) + "个文件开始上传");
String fileSizeStr = dis.readUTF();
System.out.println("文件长度" + fileSizeStr);
String fileName = dis.readUTF();
System.out.println("文件名称" + fileName);
StringBuilder filePath = new StringBuilder();
filePath.append("E:/").append(fileNumber);
File fileCatalog = new File(filePath.toString());
if (!fileCatalog.exists())
fileCatalog.mkdirs();
filePath.append("//").append(fileName);
File file = new File(filePath.toString());
FileOutputStream fos = new FileOutputStream(file);
byte[] buffer = new byte[1024];
System.out.println("开始接收文件"); int len = 0;
int count = 0;
while ((len = dis.read(buffer, 0, 1024)) != -1) {
fos.write(buffer, 0, len);
fos.flush();
}
fos.close();
System.out.println("文件" + fileNumber + "上传完毕");
} catch (IOException e) {
e.printStackTrace();
}
}
}应该是好使的。
感谢二位朋友的关注,问题应该就在这里了,leisore朋友分析的很有道理,但是现在我还有一点不明白,为什么我以前的写法中,把byte数组的长度改大(我改成了1M个字节的长度),为什么就能上传完整的文件呢,按照leisore朋友的分析,就是改到多大也应该是不对的,而且我测试中,如果btye数组长度是1024时,测试上传的所有文件大小都是差1024*16个字节的。
按照leisore朋友的分析,确实把数据丢失在那了一部分,但是按照我以前的写法,把byte数组长度调大,确实也可以正常接收文件了,就是不明白这个地方到底是为什么。
Java code
File file = new File("F://java文档资料//api//html_zh_CN.zip");
//FileInputStream fis = new FileInputStream(file);
DataInputStream fis = new DataInputStream(new FileInputStream(file));
long fileSize = fis.available();
String fileName = file.getName();
s = new Socket("127.0.0.1", 10000);
System.out.println("已经连接上服务器");
DataOutputStream os = new DataOutputStream(s.getOutputStream());
PrintWriter pw = new PrintWriter(os, true);
============================================================================================
你传的文件是 rar,即二进制文件你用的输出是XXXWriter,Writer是用来写文本的,即字符流,这么做必然丢数据。你把传输的文件换成文本文件应该就没问题了,要么把XXXWriter换成操作字节的输出者。
楼主要弄清楚,到底是要传输文件,还是要传输文件的内容。
如果只传输文件的内容,就要杜绝文件大小等信息的传输。
Socket通信,底层采用TCP协议,不会出现丢包现象。ObjectOutputStream,这个类,是用来传输可序列化的对象,File对象不可被序列化吧 ?如果楼主非要将文件的名称和大小传输到对方,那就要自己定义一个简单点的协议。
(或者说,传输数据的数据格式)然后,收发双方遵照协议,即可。楼主的程序,有两大败笔。
首先,数据的发送方式,前后不一致。
前面两个数据以对象的形式进行发送,后面的文件内容,采用二进制byte数组形式发送。
根据编程理念来将,可以通篇使用ObjectOutputStream发送信息,byte数组也可以看作可序列化的对象。
其次,数据的接收方面,在数据格式 前后不一致的情况下 前者采用的缓冲区进行处理。
这是一个致命的错误。为什么呢 ?
前面读入的数据,从缓冲区里面读取。后面的数据没有从同一缓冲区里面读取。
会造成缓冲区里面会驻留一些缓冲数据无法被程序读取出来。