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


«September 2025»
123456
78910111213
14151617181920
21222324252627
282930


公告

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


我的分类(专题)

日志更新

最新评论

留言板

链接

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




[java语言]java的ServerSocket的中如何知道客户端的关闭 
原创空间,  软件技术,  电脑与网络

邢红瑞 发表于 2007/4/11 16:44:20

以前使用很少使用java的ServerSocket编程,主要使用nio的ServerSocketChannel.从没有注意到这个问题,客户端的socket发出Close指令后,服务器为什末是抛出异常关闭.而不是更柔和的办法.看了看jdk的c代码,Java的Socket读取函数 switch (WSAGetLastError()) {         case WSAEINTR:      JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",    "socket closed");      break;   case WSAECONNRESET:  case WSAESHUTDOWN:      /*       * Connection has been reset - Windows sometimes reports       * the reset as a shutdown error.       */      JNU_ThrowByName(env, "sun/net/ConnectionResetException",   "");      break;          case WSAETIMEDOUT :                    JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",                                   "Read timed out");      break;   default:      NET_ThrowCurrent(env, "recv failed");     }如果调用WSAGetLastError(),客户端关闭连接,返回多数是WSAECONNRESET,这是jvm要抛出ConnectionResetException,注意这不是java的标准异常,我们没有捕捉它.这里是微软msdn 错误码的详细描述  http://msdn2.microsoft.com/en-us/library/ms740668.aspx打开SocketInputStream.java // acquire file descriptor and do the read FileDescriptor fd = impl.acquireFD();  try {      n = socketRead0(fd, b, off, length, impl.getTimeout());     if (n > 0) {  return n;     } } catch (ConnectionResetException rstExc) {     gotReset = true; } finally {     impl.releaseFD(); }  /*  * We receive a "connection reset" but there may be bytes still  * buffered on the socket  */ if (gotReset) {     impl.setConnectionResetPending();     impl.acquireFD();     try {         n = socketRead0(fd, b, off, length, impl.getTimeout());  if (n > 0) {      return n;  }     } catch (ConnectionResetException rstExc) {     } finally {  impl.releaseFD();     } }  /*  * If we get here we are at EOF, the socket has been closed,  * or the connection has been reset.  */        if (impl.isClosedOrPending()) {            throw new SocketException("Socket closed");        } if (impl.isConnectionResetPending()) {     impl.setConnectionReset(); }  if (impl.isConnectionReset()) {     throw new SocketException("Connection reset"); } eof = true; return -1;    }注意抛出ConnectionResetException后,socket的buffer还有数据,最后如果connection被重置,抛出SocketException,这个异常是IOException的子类,大家catch IOException就行了.所以客户端的socket发出Close指令后,服务器是抛出异常关闭.对此sun也有它的苦衷,java的io设计是跨平台,代码移植不应该有任何差异,所以只好提取了所有平台的共性.java的nio针对各个平台写的,写出的代码不保证跨平台的移植.另外说一句题外话,我看Java Network Programming, 3rd Edition时,发现客户端关闭连接,抛出InterruptedIOException,这个异常一般是超时抛出的,原因就是I/O 操作已中断信号。抛出 InterruptedIOException 指示输入或输出传输已经终止,原因是执行此操作的线程中断。我得继续研究一下,windows网络编程了,多年不用,生锈了,这次得到好友kei和cyt的帮助,表示感谢. 经好友象风确认,对于阻塞模式,只要客户端不关闭,或者网络不断开,服务器端的socket连接不关闭,阅读Java Network Programming, 3rd Editionpublic boolean isConnected( ) // Java 1.4   The name is a little misleading. It does not tell you if the socket is currently connected to a remote host (that is, if it is unclosed). Instead it tells you whether the socket has ever been connected to a remote host. If the socket was able to connect to the remote host at all, then this method returns true, even after that socket has been closed. To tell if a socket is currently open, you need to check that isConnected( ) returns true and isClosed() returns false. For example:boolean connected = socket.isConnected( ) && ! socket.isClosed( );问了问,Thomas Schodt,告诉我This will tell you ifclose()connect()etc.have been called on the socket at *your* end, not at the *other* end 


阅读全文(7143) | 回复(1) | 编辑 | 精华
 


回复:java的ServerSocket的中如何知道客户端的关闭
原创空间,  软件技术,  电脑与网络

老姚(游客)发表评论于2007/4/12 13:42:13

老邢这几年的你没有白活,开始研究JVM了


个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除
 


» 1 »

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



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

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