本站首页    管理页面    写新日志    退出


«September 2025»
123456
78910111213
14151617181920
21222324252627
282930


公告

戒除浮躁,读好书,交益友


我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:邢红瑞的blog
日志总数:523
评论数量:1142
留言数量:0
访问次数:9712304
建立时间:2004年12月20日




[java语言]透过socket关闭输入流,而关闭socket看java网络编程的实现
原创空间,  软件技术,  电脑与网络

邢红瑞 发表于 2007/4/15 10:05:50

 最近很不幸,遇到很多java socket的问题,例如关闭Socket的输入流,整个socket会关闭吗.调用socket.getInputStream().close(),socket的isClosed()确实返回true, 这时如果你调用socket的isInputShutdown()和isOuputShutdown返回false.看了看sun的代码,明白了一些,调用Socket的getInputStream(),中调用了一个SocketImpl的引用,SocketImpl是一个抽象类.它强迫子类继承他的getInputStream()方法,PlainSocketImpl是SocketImpl的子类.PlainSocketImpl的getInputStream()方法返回SocketInputStream.PlainSocketImpl创建流后,传入SocketInputStreamConstructor的函数中.SocketInputStream的close方法   /**     * Closes the stream.     */    private boolean closing = false;    public void close() throws IOException { // Prevent recursion. See BugId 4484411 if (closing)     return; closing = true; if (socket != null) {     if (!socket.isClosed())  socket.close(); } else     impl.close(); closing = false;    }此时,PlainSocketImpl已经关闭了,我们再调用Socket.getOutputStream()就会抛出SocketException./**     * Gets an InputStream for this socket.     */    protected synchronized InputStream getInputStream() throws IOException { if (isClosedOrPending()) {     throw new IOException("Socket Closed"); } if (shut_rd) {     throw new IOException("Socket input is shutdown"); } if (socketInputStream == null) {     socketInputStream = new SocketInputStream(this); } return socketInputStream;    }     void setInputStream(SocketInputStream in) { socketInputStream = in;    }/**     * Closes the socket.     */    protected void close() throws IOException { synchronized(fdLock) {     if (fd != null || fd1 != null) {  if (fdUseCount == 0) {      if (closePending) {   return;      }      closePending = true;      /*       * We close the FileDescriptor in two-steps - first the        * "pre-close" which closes the socket but doesn't       * release the underlying file descriptor. This operation       * may be lengthy due to untransmitted data and a long       * linger interval. Once the pre-close is done we do the       * actual socket to release the fd.       */      try {          socketPreClose();      } finally {          socketClose();      }      fd = null;      fd1 = null;      return;  } else {      /*       * If a thread has acquired the fd and a close       * isn't pending then use a deferred close.       * Also decrement fdUseCount to signal the last       * thread that releases the fd to close it.       */      if (!closePending) {   closePending = true;          fdUseCount--;   socketPreClose();      }  }     } }    }在linux下真是这样,但是在windows下,socket不是马上关闭的,不信你就用netstat -an看一下(关闭流,而不是关闭socket)。偶尔发现sniffer pro的一个bug,我用java发送375个byte的数据,php收到375个,但是sniffer显示tcp数据374个字节,最后使用Ethereal看了看就是375个,浪费我半天时间。说到java的网络编程,我公布一下陈睿的看法,最近常被问到的一个问题是:做高效率的网络应用都是用C/C++,为什么要用Java?我也一直在思考这个问题,这牵涉到Cindy的定位,以及将来的发展方向。如果存在一个这样的假设:C/C++和Java在网络处理方面拥有接近的运行效率,你会选择用什么语言开发网络应用?我的答案会是Java。为什么?因为对于大部分普通程序员而言(某些C/C++高手除外),在业务逻辑的开发效率上,Java要超出C/C++许多,这也正是Java流行起来的原因。但是遗憾的是,这个假设目前还不存在:( JSR 203提议在Java中加入对操作系统本身异步IO的支持,但没有人推动;IBM推出过aio4j,不开源,而且在2004年就停止了更新。所以目前在你所看到的现实中,这类应用仍旧是C/C++的天下。虽然假设并不存在,但需求是切切实实存在的:大家对Java网络方面的效率有着更高的期望。比如Tomcat,在它的5.5版本中有基于ARP的JNI实现;比如Resin以及其他很多商业WEB服务器,都有JNI的实现。但是遗憾的是,这些JNI并不是一个独立的网络框架,所以虽然这些人都在自己发明轮子,但是其他人很难用上他们发明好的轮子。 既然有需求,而且需求无法得到满足,那么这里就有机会。做为一个比较资深的Java程序员,做为一个Java网络框架的开发者,我所关心的是:能不能让这个假设成为现实?或者能不能缩小它们的差距,给Java这边加些砝码?这就是Cindy的长远目标。目前虽然我的能力离实现这个目标还有差距,不过只要目标清晰,一直往前走,总是能实现的。对此,我的意思是网络编程中cpu的效率远高于网络的效率,一般是cpu在等网络传输,java在cpu指令执行部分的确不如c++,但是java在内存分配占有优势,这也就是resin抗负载能力,不次于apache的一个原因。最后对广大java程序员说一句,"平台有差异,编程需谨慎"。


阅读全文(11529) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.047 second(s), page refreshed 144795399 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号