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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 向前看向前走 中级黑马   /  2014-5-17 11:11  /  2508 人查看  /  20 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 向前看向前走 于 2014-5-18 10:12 编辑

在看毕老师的视频,在TCP上传图片这一块,看到多线程时开了服务器端口,却没有关闭服务器,造成端口一直被占用,请用是怎么回事,视频中好像有截取,把这一块的讲解给漏了
服务端代码
public static void main(String[] args) throws Exception
{
  // TODO Auto-generated method stub
      ServerSocket sk = new ServerSocket(10015);
      while(true){
      Socket sc = sk.accept();
      
      new Thread(new ThreadDemo(sc)).start();
      
      }
    //sk.close(); 在视频中为什么在注掉这个,没有说明
      
   
}

多线程的代码
Socket sc = null;
   //String ip = sc.getInetAddress().getAddress().toString();
public ThreadDemo(Socket sc)
{
  this.sc=sc;
  
}
public void run()
{
  try {
   
   int count =0;
   File file = new File("d:\\q"+count+".crd");
   while(file.exists())
   {
    count++;
   }
   FileOutputStream  fis = new FileOutputStream("d:\\q"+count+".crd");
      
        InputStream is = sc.getInputStream();
        
        byte[] data = new byte[1024];
        int len=0;
        
        while((len = is.read(data))!=-1)
        {
         fis.write(data);
        }
        OutputStream ops = sc.getOutputStream();
        ops.write("谢谢".getBytes());
        sc.close();
  } catch (Exception e) {
   throw new  RuntimeException("失败了");
   }
      
}




20 个回复

倒序浏览
名为服务器,就是一直开着的。这里用了多线程就是为了让不同的客户端都可以上传图片,就像你什么时候都可以访问百度,百度服务器也是开着的说。
回复 使用道具 举报
本帖最后由 向前看向前走 于 2014-5-17 11:29 编辑
skill20 发表于 2014-5-17 11:25
名为服务器,就是一直开着的。这里用了多线程就是为了让不同的客户端都可以上传图片,就像你什么时候都可以 ...


我想关掉怎么办,不想一直开着,我调试用,为什么去掉注释就报错
回复 使用道具 举报
向前看向前走 发表于 2014-5-17 11:27
我想关掉怎么办,不想一直开着,我调试用,为什么去掉注释就报错

那就不要开启多线程。
回复 使用道具 举报
服务器,就是要一直开着的处于连接状态,因为为了满足不同的用户来和它连接,所以最好是保持连接状态,当然也是可以关闭的,正常来说不用关闭的,你把自己的文件传输完了,关闭自己的传输流就可以了。
回复 使用道具 举报
没有我想要的答案,也谢谢各位了
回复 使用道具 举报
其实你提的是三个问题:
1.为什么要注释掉主函数的最后一行代码,因为这段代码时执行不到的,while循环不存在结束条件,因而根本执行不到。
2.为什么没有结束服务端,这个是符合日常的需求的,服务端就像是window系统,是个死循环的东东,不需要结束的,除非强制性停止。
3.至于你说的为什么多线程时开了服务器端口,却没有关闭服务器,造成端口一直被占用,可以用以上的两个解释的,这么来比喻吧,文件的操作你知道的吧,首先也是要用流对象和文件建立连接的,最后需要关闭这个流对象,也就是关闭连接,那么服务器端口也是这样的,因为写的都是死循环程序,所以不可能关闭端口的,就算是关闭,也是由于强制关闭导致的,由于强制关闭呢,我们没有处理异常,因而才导致端口没有关闭,考虑到这里,你可能会说,是不是我们可以仿照文件的处理方式关闭强制导致的端口占用的问题,即关闭ServerSocket呢?答案是有可能的,前提是你将客户端的强制性关闭(如果强制性关闭服务端,还是会有这个问题的),然后服务器就能看到效果了,这是我写的一个小例子,希望可以帮到你.

  1. public class SocketCloseTest {
  2.         public static void main(String[] args) throws Exception {
  3.                 ServerSocket ss= null;
  4.                 try {
  5.                         ss = new ServerSocket(10006);
  6.                         ss.accept();
  7.                 } catch (Exception e) {
  8.                         System.out.println("异常中断服务器的运行");
  9.                         e.printStackTrace();
  10.                 }finally{
  11.                         try {
  12.                                 if(ss!=null){
  13.                                         ss.close();
  14.                                 }
  15.                         } catch (Exception e) {
  16.                                 System.out.println("Server socket关闭异常");
  17.                                 e.printStackTrace();
  18.                         }finally{
  19.                                 ss = null;
  20.                         }
  21.                 }
  22.         }
  23. }
复制代码


评分

参与人数 1技术分 +1 收起 理由
轻语。 + 1

查看全部评分

回复 使用道具 举报
改造了一下子,希望有帮助吧
  1. import java.io.File;
  2. import java.io.FileOutputStream;
  3. import java.io.OutputStream;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;

  6. import org.omg.CORBA.portable.InputStream;

  7. public class tezt1 {
  8.         public static void main(String[] args) throws Exception
  9.          {
  10.            // TODO Auto-generated method stub
  11.                ServerSocket sk = new ServerSocket(10015);
  12.                while(true){
  13.                Socket sc = sk.accept();
  14.                //给个提示信息
  15.                System.out.println("客户端已连接!!") ;
  16.                new Thread(new ThreadDemo(sc)).start();
  17.                }
  18.              //sk.close(); 在视频中为什么在注掉这个,没有说明
  19.              //我觉得上面是一个死循环,没必要结束,除非程序结束
  20.          }
  21. }

  22.         //多线程的代码
  23. class ThreadDemo implements Runnable{
  24.         Socket sc = null;
  25.             //String ip = sc.getInetAddress().getAddress().toString();
  26.          public ThreadDemo(Socket sc)
  27.          {
  28.            this.sc=sc;
  29.           
  30.          }
  31.          public void run()
  32.          {
  33.            try {  
  34.               int count =0;
  35.               File file = new File("d:\\q"+count+".crd");
  36.               while(file.exists())
  37.               {
  38.                count++;
  39.               }
  40.               FileOutputStream  fis = new FileOutputStream("d:\\q"+count+".crd");
  41.                 
  42.               InputStream is = (InputStream) sc.getInputStream();
  43.                 
  44.               byte[] data = new byte[1024];
  45.               int len=0;
  46.                 
  47.               while((len = is.read(data))!=-1)
  48.               {
  49.                 fis.write(data);
  50.               }
  51.               OutputStream ops = sc.getOutputStream();
  52.               ops.write("谢谢".getBytes());
  53.               sc.close();
  54.            } catch (Exception e) {
  55.             throw new  RuntimeException("失败了");
  56.             }
  57.                
  58.          }
  59. }
复制代码
回复 使用道具 举报
本帖最后由 向前看向前走 于 2014-5-18 00:25 编辑
pandapan 发表于 2014-5-17 19:00
其实你提的是三个问题:
1.为什么要注释掉主函数的最后一行代码,因为这段代码时执行不到的,while循环不存 ...


     看到了你的回答,为我解析了原理,对于你说的三点,第一个我明白了为什么那个代码报错了,但是第二个我还是有一点不明白,就像你说windows服务,虽然是一个死循环,但是在服务卸载的时候还是会释放所有资源的,所以我是想知道怎么在这一块代码中加入相当于卸载的功能。就是让这个服务器用代码去释放所有资源,第三这个demo我是用ecliplse中写的,不知道知道去强制关闭服务端和客户端程序,只是点了一下运行。
   不过总算知道原因了,谢谢啦!

评分

参与人数 1技术分 +1 收起 理由
轻语。 + 1

查看全部评分

回复 使用道具 举报
心?=忐§忑] 发表于 2014-5-17 19:00
改造了一下子,希望有帮助吧

感谢回答,不过对我帮助不大!
回复 使用道具 举报
呵呵呵呵呵,你再看看TCP和UDP教程吧
回复 使用道具 举报
本帖最后由 pandapan 于 2014-5-18 07:27 编辑

回复 使用道具 举报
本帖最后由 pandapan 于 2014-5-18 10:17 编辑
向前看向前走 发表于 2014-5-18 00:22
看到了你的回答,为我解析了原理,对于你说的三点,第一个我明白了为什么那个代码报错了,但是第二 ...

首先,值得肯定的是,你的想法很好。
1. 我给你写的改造后的代码就可以实现了释放资源的功能呢,不过是必须客户端强制性终止,你想想,如果服务端强制性终止的话,都已经终止了,他还会执行咱们写的代码吗?肯定不会的啦,所以呢,这个想释放资源,是有前提条件的,那就是必须客户端强制性种终止。(eclispe中强制终止的话,是有按钮的,但是如果服务端和客户端同时在一个eclispe,不知道会不会都终止,因而建议开启两个eclispe,一个运行服务端,一个运行客户端,这样的模拟才逼真嘛,关闭使用哪个按钮的图放到我的帖子的最后)
2. 再来打个比方吧,这个比较合适。在eclispe中开启tomcat服务,对于我们正常的关闭eclispe(相当于我们的服务端和客户端正常结束),eclispe也会将javaw服务关闭的,但是如果我们强制性关闭eclispe进程呢?(这个相当于我们的服务端强制性结束)这个就有可能导致tomcat服务不能关闭,因而在再次打开eclispe后启动web工程会报错的,这时我们会强制性的杀javaw进程,然后再启动web工程,就好了。这个例子是比较合适的。
3. 我的那个windows系统的比喻只是为了说明死循环的问题,说释放资源就不太合适了,说到释放资源,window系统所谓的关机和释放资源,可以认为是关闭端口和清空内存了,是吧,windows端口本来就是一个逻辑的定义,内存只是临时性的存储介质,非永久性的,所以系统重启后端口和内存都是空白的,是操作系统和软件指定打开哪些端口,系统才打开,内存在系统重启后,只是需要加载哪些,才去加载。希望能够帮到你。



eclipse终止按钮terminate.jpg (147.48 KB, 下载次数: 4)

eclipse终止按钮terminate

eclipse终止按钮terminate

评分

参与人数 1技术分 +1 收起 理由
轻语。 + 1 赞一个!

查看全部评分

回复 使用道具 举报
pandapan 发表于 2014-5-18 07:50
首先,值得肯定的是,你的想法很好。
1. 我给你写的改造后的代码就可以实现了释放资源的功能呢,不过是必 ...

感谢你的回答
      今天我又试验了一下,问题是解决了
      首先我用的是一个Eclipse,然后执行这一个循环,占用了这个端口,而毕老师在讲的时候生成的是程序,而我是借助Eclipse平台运行的,在运行的过程还有那个红色的按钮,而客户端一接入成功上传之后就没有了,后来我也百度了一下这个问题,发现虽然在Eclipse显示没有运行,但是在进程中还是有一个javac.exe在运行的,在任务管理器中把它给关闭了,然后再运行就正常了,如果是正常的程序关闭就不用有这个问题吧。
     你说的开两个Eclipse也会出现这个问题吧,这个应该Eclipse本身的问题,它应该提供一个终止循环的按钮,而不是一直占用着,而看起来和平常一样!

从第二张图片可以看出来占用CPU是相当大的,这个还得加个线程的时间控制

评分

参与人数 1技术分 +1 收起 理由
轻语。 + 1

查看全部评分

回复 使用道具 举报
向前看向前走 发表于 2014-5-18 10:07
感谢你的回答
      今天我又试验了一下,问题是解决了
      首先我用的是一个Eclipse,然后执行这一个循 ...

同学,准备参加那期呢?交个朋友吧。
回复 使用道具 举报
高质量提问解答帖子 就应该是这样的。及时标识提问结束。不然我还差点错过。
回复 使用道具 举报
伍叶竹 发表于 2014-5-18 10:27
高质量提问解答帖子 就应该是这样的。及时标识提问结束。不然我还差点错过。 ...

那么版主 要设置为精华吗?:lol:lol:lol
回复 使用道具 举报
pandapan 发表于 2014-5-18 10:32
那么版主 要设置为精华吗?

精华帖要求太高。。。
      继续加油哈。
回复 使用道具 举报
pandapan 发表于 2014-5-18 10:15
同学,准备参加那期呢?交个朋友吧。

基础视频还没有看完了,我估计得6月份了
回复 使用道具 举报
伍叶竹 发表于 2014-5-18 10:35
精华帖要求太高。。。
      继续加油哈。

看来还得继续努力呀
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马