mina 拔掉了网线还能发送数据?费解

yinrongg 2014-04-24 10:17:04
做了一个简单mina通信客户端和服务端(测试时客户端和服务端是用不同到电脑测试的),服务端程序很简单,接收到客户端发送到程序后返回,设置session超时5秒,超时后关闭session。
客户程序也很简单:unbutu10.04系统下,使用长连接,每隔2秒向服务端发送一个字符串。当检测到session已经关闭时重新连接并再次发送,现在碰到到问题是,当客户端在正常运行时拔掉网线,此时按理说,session.write时应该会激发异常,但现在却无任何异常,当拔掉网线时间超过服务端设置的超时时间后,插上网线,客户端也不能正常向服务端发送数据。以下所客户端代码:


import com.sun.swing.internal.plaf.metal.resources.metal;
import com.sun.swing.internal.plaf.metal.resources.metal_sv;
import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.SocketConnector;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

import java.net.ConnectException;
import java.net.InetSocketAddress;

public class MinaClient {
public SocketConnector socketConnector;

/**
* 缺省连接超时时间
*/
public static final int DEFAULT_CONNECT_TIMEOUT = 5;

public static final String HOST = "192.168.0.100";

public static final int PORT = 1100;

public static IoSession ioSession;

public MinaClient() {
init();
}

public void init() {
socketConnector = new NioSocketConnector();

// 长连接
socketConnector.getSessionConfig().setKeepAlive(true);

socketConnector.setConnectTimeoutMillis(DEFAULT_CONNECT_TIMEOUT * 1000);

socketConnector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory()));

ClientIoHandler ioHandler = new ClientIoHandler();
socketConnector.setHandler(ioHandler);
InetSocketAddress addr = new InetSocketAddress(HOST, PORT);
ConnectFuture cf = socketConnector.connect(addr);
cf.awaitUninterruptibly();
ioSession = cf.getSession();
}

public void sendMessage(final String msg) {
try {
if (ioSession != null) {
if (ioSession.isConnected()) {//拔掉网线后,此处该false
ioSession.write(msg);//此处拔掉网线后不激发异常?
System.out.println("send message " + msg);
} else {
reconnect();
}
}

} catch (RuntimeIoException e) {
e.printStackTrace();
}
}

private void reconnect() {
InetSocketAddress addr = new InetSocketAddress(HOST, PORT);
ConnectFuture cf = socketConnector.connect(addr);
cf.awaitUninterruptibly();
ioSession = cf.getSession();
}

public static void main(String[] args) throws InterruptedException {
MinaClient clent = new MinaClient();
for (int i = 0; i < 99999; i++) {
Thread.sleep(2000);
System.err.println(i);
clent.sendMessage("Hello World " + i);
}
clent.getSocketConnector().dispose();

}

public SocketConnector getSocketConnector() {
return socketConnector;
}

public void setSocketConnector(SocketConnector socketConnector) {
this.socketConnector = socketConnector;
}


}

class ClientIoHandler extends IoHandlerAdapter {

private void releaseSession(IoSession session) throws Exception {
System.out.println("releaseSession");
if (session.isConnected()) {
session.close(true);
}
}

@Override
public void sessionOpened(IoSession session) throws Exception {
System.out.println("sessionOpened");
}

@Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println("sessionClosed-c");
}

@Override
public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
System.out.println("sessionIdle");
try {
releaseSession(session);
} catch (RuntimeIoException e) {
}
}

@Override
public void messageReceived(IoSession session, Object message) throws Exception {
System.out.println("Receive Server message " + message);

}

@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
System.out.println("exceptionCaught");
cause.printStackTrace();
releaseSession(session);
}

@Override
public void messageSent(IoSession session, Object message) throws Exception {
System.out.println("messageSent");
super.messageSent(session, message);
}

}

服-务端代码如下:

import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

import java.net.InetSocketAddress;

public class MinaServer {

public void init() throws Exception{
SocketAcceptor acceptor = new NioSocketAcceptor(Runtime.getRuntime().availableProcessors() + 1);
//设置解析器
DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
chain.addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory()));

acceptor.setHandler(new BexnHandler());
acceptor.bind(new InetSocketAddress(1100));
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,5);

}
public MinaServer() throws Exception {
init();
}

public static void main(String[] args) throws Exception {
new MinaServer();
System.out.println("Server start");
}
}

class BexnHandler extends IoHandlerAdapter {
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
System.out.println("messageReceived " + message);
super.messageReceived(session, message);
session.write("messageReceived "+message);

}

@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
if (session.isConnected()) {
session.close(true);
}
}

@Override
public void messageSent(IoSession session, Object message) throws Exception {
// session.close();
}

@Override
public void sessionClosed(IoSession session) throws Exception {
super.sessionClosed(session);
System.out.println("sessionClosed-s");
}

@Override
public void sessionCreated(IoSession session) throws Exception {
}

@Override
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
session.close(true);
}

@Override
public void sessionOpened(IoSession session) throws Exception {
super.sessionOpened(session);
}
}


求解惑阿?
...全文
356 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
yinrongg 2014-04-27
  • 打赏
  • 举报
回复
引用 6 楼 wad12302 的回复:
不管在哪个平台,这都是一个致命问题。 采用长连接 必须要加心跳机制了,长连接肯定不会很多上千,所以心跳是需要添加的, 看你们的业务量,多久一次心跳, 同时还有另外一个问题: 比如30秒心跳:中间断开15秒后,网络又恢复了,那么30秒的心跳是无法检测出来了,所以心跳时候应该加上版本版判断是否网络已经出现过断开过,不然 你心跳成功,其实长连接已经失效。 但是我们生产环境 服务器与长连接的客户端是内外,我们的心跳就没有检测版本,就是简单的心跳,心跳成功就说明网络正常
我现在是服务器设置与客户端的session 30秒就超时,客户端使用长连接,15秒钟发送一次心跳。
济南大飞哥 2014-04-26
  • 打赏
  • 举报
回复
引用 2 楼 ling3wei 的回复:
java板块的人比.net板块的人活跃的少啊,真是个奇怪的现象
原因是java的很多东西该研究的都研究出来了,再加上框架的出现,很多问题 一百度就出来了,往日那种纠结“小粒度”的问题的现象少了,CSDN也就不火了。
wad12302 2014-04-26
  • 打赏
  • 举报
回复
不管在哪个平台,这都是一个致命问题。 采用长连接 必须要加心跳机制了,长连接肯定不会很多上千,所以心跳是需要添加的, 看你们的业务量,多久一次心跳, 同时还有另外一个问题: 比如30秒心跳:中间断开15秒后,网络又恢复了,那么30秒的心跳是无法检测出来了,所以心跳时候应该加上版本版判断是否网络已经出现过断开过,不然 你心跳成功,其实长连接已经失效。 但是我们生产环境 服务器与长连接的客户端是内外,我们的心跳就没有检测版本,就是简单的心跳,心跳成功就说明网络正常
yinrongg 2014-04-26
  • 打赏
  • 举报
回复
引用 4 楼 wad12302 的回复:
不用看了,肯定发不了的, 因为我当初项目就这样测试过, 为什么呢?因为拔掉网线 mina没有心跳(或者是检测网络太慢),无法检查网络,同时 mina是异步的,只管得到数据就write ,你的消息就丢失了 他的异常捕获机制不够完善,要等到2 ,3 分钟后才捕获异常,而且还不一第一个信息的一次,可能是时间太久了已经判断出网络问题抛的
拔掉网线,linux下session.write不抛异常,这个很郁闷。windows下抛异常就很快。那您是怎么应对这种情况的?
去旅行吧 2014-04-25
  • 打赏
  • 举报
回复
有时候拔掉网线后客户端没有异常很正常,客户端应该自己检测自己是否在线。还有你重连成功了吗 如果成功了应该不会出现“客户端也不能正常向服务端发送数据”的情况。
wad12302 2014-04-25
  • 打赏
  • 举报
回复
不用看了,肯定发不了的, 因为我当初项目就这样测试过, 为什么呢?因为拔掉网线 mina没有心跳(或者是检测网络太慢),无法检查网络,同时 mina是异步的,只管得到数据就write ,你的消息就丢失了 他的异常捕获机制不够完善,要等到2 ,3 分钟后才捕获异常,而且还不一第一个信息的一次,可能是时间太久了已经判断出网络问题抛的
yinrongg 2014-04-24
  • 打赏
  • 举报
回复
java板块的人比.net板块的人活跃的少啊,真是个奇怪的现象
yinrongg 2014-04-24
  • 打赏
  • 举报
回复
帖子终于发出来了,下午发了一下午说非法字符,那个郁闷啊

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧