项目中遇到一个需求,需要安卓多客户端连接java后台进行相互通信,保持长连接,所以想到用socket来做,在网上看了一堆资料后,发现了mina框架,下面把自己整合的代码记录一下。
jar包自己在网上找,这里就不贴了
1、首先创建一个线程类,创建服务端的socket并且绑定指定的端口
public class SocketTest implements Runnable{
//日志类的实现
private static Logger logger = Logger.getLogger(SocketTest.class+"");
//端口号,要求客户端与服务器端一致
private static int PORT = 9088;
@Override
public void run() {
IoAcceptor acceptor = null;
try{
//创建一个非阻塞的server端的Socket
acceptor = new NioSocketAcceptor();
//设置过滤器(使用mina提供的文本换行符编解码器)(在bind前进行)
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"),LineDelimiter.WINDOWS.getValue(),LineDelimiter.WINDOWS.getValue())));
//自定义的编解码器
//acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new CharsetCodecFactory()));
//设置读取数据的换从区大小
acceptor.getSessionConfig().setReadBufferSize(2048);
//读写通道10秒内无操作进入空闲状态
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
//为接收器设置管理服务
acceptor.setHandler(new SocketHandlerTest());
//绑定端口
acceptor.bind(new InetSocketAddress(PORT));
logger.info("服务器启动成功... 端口号未:"+PORT);
}catch(Exception e){
logger.info("服务器启动异常..."+e.getMessage().toString());
e.printStackTrace();
}
}
}
2、然后创建监听器,在项目启动的同时启动socket服务,等待客户端连接
public class InitListener implements ApplicationListener<ContextRefreshedEvent>{
//日志类的实现
private static Logger logger = Logger.getLogger(InitListener.class+"");
@Override
public void onApplicationEvent(ContextRefreshedEvent arg0) {
logger.info("执行监听器...");
new Thread(new SocketTest()).start();
}
}
3、最后编写处理类继承IoHandlerAdapter对socket进行管理
public class SocketHandlerTest extends IoHandlerAdapter{
public static Logger logger = Logger.getLogger(SocketHandlerTest.class + "");
// 从端口接受消息,会响应此方法来对消息进行处理
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
String msg = message.toString();
System.out.println(msg);
String m = (String) session.getAttribute("clientIP");
logger.info(m);
/* //展现解析json得到的值
StringBuffer buf = new StringBuffer();
try {
//解析传递的json
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(msg);
} catch (Exception e) {
// TODO: handle exception
}*/
if ("exit".equals(msg)) {
// 如果客户端发来exit,则关闭该连接
session.close(true);
}
// 向客户端发送消息
Date date = new Date();
session.write(date);
logger.info("服务器接受消息成功..." + msg);
super.messageReceived(session, message);
}
// 向客服端发送消息后会调用此方法
@Override
public void messageSent(IoSession session, Object message) throws Exception {
logger.info("服务器发送消息成功...");
super.messageSent(session, message);
}
// 关闭与客户端的连接时会调用此方法
@Override
public void sessionClosed(IoSession session) throws Exception {
logger.info("服务器与客户端断开连接...");
super.sessionClosed(session);
}
// 服务器与客户端创建连接
@Override
public void sessionCreated(IoSession session) throws Exception {
logger.info("服务器与客户端创建连接...");
IoSessionTest.session=session;
String clientIP = ((InetSocketAddress)session.getRemoteAddress()).getAddress().getHostAddress();
session.setAttribute("clientIP", clientIP);
logger.info(clientIP);
super.sessionCreated(session);
}
// 服务器与客户端连接打开
@Override
public void sessionOpened(IoSession session) throws Exception {
logger.info("服务器与客户端连接打开...");
super.sessionOpened(session);
}
@Override
public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
logger.info("服务器进入空闲状态...");
super.sessionIdle(session, status);
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
logger.info("服务器发送异常...");
super.exceptionCaught(session, cause);
}
}
这样服务端也可以主动发消息给客户端,对MINA包下的IoSession进行操作,可以实现多客户端连接且保持长连接的需求