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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© igi9009 中级黑马   /  2014-4-24 14:47  /  961 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

Socket s = ss.accept();
我想知道这里为什么不放到run方法中,
而下面的开启线程传入的Runnable实现类就不需要
传入Socket对象了,通过线程启动后,在创建Socket对象。
  1. /*
  2. 需求:上传图片。

  3. */
  4. /*
  5. 客户端。
  6. 1,服务端点。
  7. 2,读取客户端已有的图片数据。
  8. 3,通过socket 输出流将数据发给服务端。
  9. 4,读取服务端反馈信息。
  10. 5,关闭。

  11. */

  12. import java.io.*;
  13. import java.net.*;
  14. class PicClient
  15. {
  16. public static void main(String[] args)throws Exception
  17. {
  18. if(args.length!=1)//为什么这里判断长度是1,就防止乱传参数呢?
  19. {
  20. System.out.println("请选择一个jpg格式的图片");
  21. return ;
  22. }




  23. File file = new File(args[0]);
  24. if(!(file.exists() && file.isFile()))
  25. {
  26. System.out.println("该文件有问题,要么补存在,要么不是文件");
  27. return ;

  28. }

  29. if(!file.getName().endsWith(".jpg"))
  30. {
  31. System.out.println("图片格式错误,请重新选择");
  32. return ;
  33. }

  34. if(file.length()>1024*1024*5)
  35. {
  36. System.out.println("文件过大,没安好心");
  37. return ;
  38. }




  39. Socket s = new Socket("127.0.0.1",11550);

  40. FileInputStream fis = new FileInputStream(file);

  41. OutputStream out = s.getOutputStream();

  42. byte[] buf = new byte[1024];

  43. int len = 0;

  44. while((len=fis.read(buf))!=-1)
  45. {
  46. out.write(buf,0,len);
  47. }

  48. //告诉服务端数据已写完
  49. s.shutdownOutput();

  50. InputStream in = s.getInputStream();

  51. byte[] bufIn = new byte[1024];

  52. int num = in.read(bufIn);
  53. System.out.println(new String(bufIn,0,num));

  54. fis.close();
  55. s.close();
  56. }
  57. }

  58. /*
  59. 服务端

  60. 这个服务端有个局限性。当A客户端连接上以后。被服务端获取到。服务端执行具体流程。
  61. 这时B客户端连接,只有等待。
  62. 因为服务端还没有处理完A客户端的请求,还有循环回来执行下次accept方法。所以
  63. 暂时获取不到B客户端对象。

  64. 那么为了可以让多个客户端同时并发访问服务端。
  65. 那么服务端最好就是将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求。



  66. 如何定义线程呢?

  67. 只要明确了每一个客户端要在服务端执行的代码即可。将该代码存入run方法中。
  68. */

  69. class PicThread implements Runnable
  70. {

  71. private Socket s;
  72. PicThread(Socket s)
  73. {
  74. this.s = s;
  75. }
  76. public void run()
  77. {

  78. int count = 1;
  79. String ip = s.getInetAddress().getHostAddress();
  80. try
  81. {
  82. System.out.println(ip+"....connected");

  83. InputStream in = s.getInputStream();

  84. File dir = new File("d:\\pic");

  85. File file = new File(dir,ip+"("+(count)+")"+".jpg");

  86. while(file.exists())
  87. file = new File(dir,ip+"("+(count++)+")"+".jpg");

  88. FileOutputStream fos = new FileOutputStream(file);

  89. byte[] buf = new byte[1024];

  90. int len = 0;
  91. while((len=in.read(buf))!=-1)
  92. {
  93. fos.write(buf,0,len);
  94. }

  95. OutputStream out = s.getOutputStream();

  96. out.write("上传成功".getBytes());

  97. fos.close();

  98. s.close();
  99. }
  100. catch (Exception e)
  101. {
  102. throw new RuntimeException(ip+"上传失败");
  103. }
  104. }
  105. }



  106. class PicServer
  107. {
  108. public static void main(String[] args) throws Exception
  109. {
  110. ServerSocket ss = new ServerSocket(11550);

  111. while(true)
  112. {
  113. Socket s = ss.accept();//我想知道这里为什么不放到run方法中,
  114. //而下面的开启线程传入的Runnable实现类就不需要
  115. //传入Socket对象了,通过线程启动后,在创建Socket对象。

  116. new Thread(new PicThread(s)).start();


  117. }

  118. //ss.close();
  119. }
  120. }
复制代码

1 个回复

倒序浏览
Socket s = ss.accept();这句代码中先要了解一下accept()方法
accept()方法是侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
把他放到run方法中如果客户端没连接上来,无法返回socket对象,那run()方法就停到那了,即启动着线程又在那瞎等,浪费内存。还不如在还没有启动线程时就提前连接客户端接受到socket对象,做好一切之后,再启动线程,岂不更加的合理。

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马