« | September 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | | | | | |
| 公告 |
戒除浮躁,读好书,交益友 |
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程序员说一句,"平台有差异,编程需谨慎"。 |
|
|