A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© yxz 中级黑马   /  2013-9-20 14:16  /  6066 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 yxz 于 2013-9-21 15:10 编辑

LZ遇到一个非常棘手问题了,连调试也麻烦,所以想请大家帮我看看问题出在哪里。
这个程序可以接受一个参数(文件的路径)发送参数下的文件。如果不接受参数则会监听端口。
有时候接收的文件比原始文件小。通常是启动服务端的第一次接收。
  1. import java.io.BufferedOutputStream;
  2. import java.io.BufferedReader;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import java.io.InputStream;
  8. import java.io.InputStreamReader;
  9. import java.net.ServerSocket;
  10. import java.net.Socket;
  11. import java.net.UnknownHostException;

  12. public class TextShowOnTcp {
  13.         public static void main(String[] args) throws IOException {
  14.                 int arglen=args.length;
  15.                 if(arglen==0)
  16.                         new ServerThread().start();
  17.                 else
  18.                         new SendThread(new File(args[0])).start();
  19.         }
  20. }

  21. class ServerThread extends Thread{
  22.         @Override
  23.         public void run() {
  24.                 ServerSocket Server=null;
  25.                 try {
  26.                         Server=new ServerSocket(5555);
  27.                         while(true){
  28.                                 Socket nowSocket=Server.accept();
  29.                                 BufferedReader readfilename =new BufferedReader(new InputStreamReader(nowSocket.getInputStream()));
  30.                                 File newfile = new File("C:\\"+readfilename.readLine());
  31.                                 if (!newfile.exists()){
  32.                                         BufferedOutputStream outputpath = new BufferedOutputStream(new FileOutputStream(newfile));
  33.                                        
  34.                                         InputStream filestream=nowSocket.getInputStream();
  35.                                         byte[] buffer=new byte[1024*10];
  36.                                         int len=0;
  37.                                         while ((len=filestream.read(buffer))!=-1) {
  38.                                                 outputpath.write(buffer, 0, len);
  39.                                         }
  40.                                         System.out.print("上传成功");
  41.                                         outputpath.close();
  42.                                 }
  43.                                 else {
  44.                                         nowSocket.shutdownInput();
  45.                                 }
  46.                         }
  47.                 } catch (IOException e) {
  48.                         e.printStackTrace();
  49.                 } finally{
  50.                         try {
  51.                                 Server.close();
  52.                         } catch (IOException e) {
  53.                                 e.printStackTrace();
  54.                         }
  55.                 }
  56.         }
  57. }

  58. class SendThread extends Thread{
  59.         File file=null;
  60.         public SendThread(File f) {
  61.                 file=f;
  62.         }
  63.         
  64.         @Override
  65.         public void run() {
  66.                 try {
  67.                         Socket Send = new Socket("192.168.1.204",5555);
  68.                         BufferedOutputStream Pso =new BufferedOutputStream(Send.getOutputStream());
  69.                         
  70.                         
  71.                         Pso.write((file.getName()+"\r\n").getBytes());
  72.                         Pso.flush();
  73.                         
  74.                         InputStream bin=new FileInputStream(file);
  75.                         
  76.                         byte[] buffer = new byte[1024*10];
  77.                         int len;
  78.                         while ((len=bin.read(buffer))!=-1) {
  79.                                 Pso.write(buffer,0,len);
  80.                         }
  81.                         Pso.close();
  82.                         bin.close();
  83.                         Send.close();
  84.                 } catch (UnknownHostException e) {
  85.                         e.printStackTrace();
  86.                 } catch (IOException e) {
  87.                         
  88.                 }
  89.         }
  90. }
复制代码

评分

参与人数 1技术分 +2 收起 理由
黄文伯 + 2 很给力!

查看全部评分

6 个回复

倒序浏览
亲,如问题已解决请将分类的“未解决”改为“已解决”。
以后的问题贴也要及时更改分类哦~
回复 使用道具 举报
楼主能加注释尽量要加注释啊!这样别人就很容易看出的你的代码想要做什么了.
目前我发现有两处错误
1,在服务端你同时nowSocket.getInputStream()));两次获取客户端的套接字节流,可能是这造成了部分字节数据丢失.
2,你的客户端中有两次向服务器发送数据,但中间过程你只做了flush()刷新动作.等于第一次客户端的套接输入流实际上服务端并没有收到.你应该在每次写完数据后进行一次套接输入流关闭动作.而服务上你也有两次获取客户端的套接字读取流,中间过程你不仅没有关闭服务端接受客户端的写入流,造成知道服务端最后执行nowSocket.shutdownInput();的时候全部数据才涌进来.所以就会出现你上传后的文件和源文件大小不同等原因.
下面是我同样功能的代码,你看下吧:
  1. public class TcpImage {
  2.         public static void main(String[] ages) {
  3.                 // 客户端
  4.                 new Thread(new Runnable() {
  5.                         //创建服务端套接字
  6.                         Socket sk = null;
  7.                         //定义文件读取流
  8.                         FileInputStream fis = null;
  9.                         public void run() {
  10.                                 try {
  11.                                         sk = new Socket(InetAddress.getByName("192.168.16.41"),
  12.                                                         2008);
  13.                                         OutputStream os = sk.getOutputStream();
  14.                                         //将服务获取的读取流转换成字符流
  15.                                         BufferedReader bisr = new BufferedReader(
  16.                                                         new InputStreamReader(sk.getInputStream()));
  17.                                         //获取原文件的读取流
  18.                                         fis = new FileInputStream("E:\\Images\\1.jpg");
  19.                                         byte[] bt = new byte[1024];
  20.                                         int end;
  21.                                         while ((end = fis.read(bt)) != -1) {
  22.                                                 os.write(bt, 0, end);
  23.                                         }
  24.                                         //关闭客服端的写入流  这不非常重要 如果没有关闭该流  则数据不会发送到服务端
  25.                                         sk.shutdownOutput();
  26.                                         String line;
  27.                                         while ((line = bisr.readLine()) != null) {
  28.                                                 System.out.println(line);
  29.                                         }
  30.                                 } catch (Exception e) {
  31.                                         throw new RuntimeException("客户端异常退出");
  32.                                 } finally {
  33.                                         if (fis != null) {
  34.                                                 try {
  35.                                                         fis.close();
  36.                                                 } catch (IOException e) {
  37.                                                         throw new RuntimeException("客户端服务关闭异常");
  38.                                                 }
  39.                                         }

  40.                                         if (sk != null) {
  41.                                                 try {
  42.                                                         sk.close();
  43.                                                 } catch (IOException e) {
  44.                                                         throw new RuntimeException("客户端服务关闭异常");
  45.                                                 }
  46.                                         }
  47.                                 }
  48.                         }
  49.                 }).start();
  50.                 // 服务端
  51.                 new Thread(new Runnable() {
  52.                         //创建一个服务套接字
  53.                         ServerSocket ssk = null;
  54.                         FileOutputStream fos = null;
  55.                         public void run() {
  56.                                 try {
  57.                                         ssk = new ServerSocket(2002);
  58.                                         fos = new FileOutputStream("F:\\1_copy.jpg");
  59.                                         //获取服务端接受到的客户套接字
  60.                                         Socket sk = ssk.accept();
  61.                                         //获取客户套接字的读取流对象
  62.                                         InputStream br = sk.getInputStream();
  63.                                         BufferedWriter bw = new BufferedWriter(
  64.                                                         new OutputStreamWriter(sk.getOutputStream()));
  65.                                         byte[] bt = new byte[1024];
  66.                                         int endr;
  67.                                         while ((endr = br.read(bt)) != -1) {
  68.                                                 fos.write(bt, 0, endr);
  69.                                         }
  70.                                         bw.write(sk.getInetAddress()+"成功上传");
  71.                                         bw.newLine();
  72.                                         bw.flush();
  73.                                         //关闭服务端接受的客户端套接字的写入流  这个步骤也非常重要 如果没有该步 那么服务端线程将处于线程等待机制
  74.                                         sk.shutdownOutput();
  75.                                 } catch (IOException e) {
  76.                                         throw new RuntimeException("服务端异常退出");
  77.                                 } finally {
  78.                                         if (fos != null) {
  79.                                                 try {
  80.                                                         fos.close();
  81.                                                 } catch (IOException e) {
  82.                                                         throw new RuntimeException("服务写入流关闭异常");
  83.                                                 }
  84.                                         }
  85.                                         if (ssk != null) {
  86.                                                 try {
  87.                                                         ssk.close();
  88.                                                 } catch (IOException e) {
  89.                                                         throw new RuntimeException("服务关闭异常");
  90.                                                 }
  91.                                         }
  92.                                 }
  93.                         }
  94.                 }).start();
  95.         }
  96. }
复制代码

评分

参与人数 1技术分 +2 收起 理由
潘才新 + 2

查看全部评分

回复 使用道具 举报
straw 发表于 2013-9-21 01:12
楼主能加注释尽量要加注释啊!这样别人就很容易看出的你的代码想要做什么了.
目前我发现有两处错误
1,在服务 ...

抱歉让你读了这么难看的源码。因为想要用TCP传文件名,一直有想不到好主意,才写两次getInputStream()。这样会使数据丢失,我还是有疑惑。
第一次获取数据流时是为了获取文件名,第二次是为了获取数据,问题在第一次获取时除了文件名还获取了其他数据,使第二次获取的数据不玩整。
这样理解正确吗?
回复 使用道具 举报
对是这样理解的,因为你的客户端在发送文件名给服务端的时候并没有立即关闭套接输入流,所以这些数据流服务端并没能立即接受到.再次一个服务端只能一次获取客户端的套接输入流,如果同时获取多个套接输入流可能会造成套接输入流中的数据混乱.
回复 使用道具 举报
straw 发表于 2013-9-21 11:06
对是这样理解的,因为你的客户端在发送文件名给服务端的时候并没有立即关闭套接输入流,所以这些数据流服务端 ...

非常感谢,对我帮助很大。
回复 使用道具 举报
straw 发表于 2013-9-21 01:12
楼主能加注释尽量要加注释啊!这样别人就很容易看出的你的代码想要做什么了.
目前我发现有两处错误
1,在服务 ...

技术很强大!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马