APP里面一直使用的是极光推送,推送时间有时候好,有时候差,所以一直想自己做APP长连接,自己做推送服务。网上找了 这个视频学习,https://www.imooc.com/learn/223,觉得还是讲的蛮好的,使用的MINA框架实现的。
讲的样例是实现消息推送的机制,我自己实现的样例是实现2个客户端实现消息互发。
消息推送这种一般要实现XMPP协议,我这里的样例为了简单起见,我就用户JSON传输数据。
话不多说,直接上代码吧。
服务端
需要引用的JAR包
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>2.0.16</version>
</dependency>
默认开启服务
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd "
default-lazy-init="false">
<bean id="socketAddress" class="com.cat.mina.MinaServer" >
</bean>
</beans>
package com.cat.mina;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public final class MinaServer{
private final NioSocketAcceptor acceptor = new NioSocketAcceptor();
public MinaServer(){
try{
acceptor.setHandler(new MinaServerHandler());
acceptor.getFilterChain().addLast("codecc", new ProtocolCodecFilter(new MinaTextFactory()));
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 5);
acceptor.bind(new InetSocketAddress(5222));
}catch(IOException e){
e.printStackTrace();
}
}
}
package com.cat.mina;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;
public class MinaTextFactory implements ProtocolCodecFactory{
private MinaTextEncode encode;
private MinaTextDecode decode;
public MinaTextFactory(){
encode = new MinaTextEncode();
decode = new MinaTextDecode();
}
@Override
public ProtocolDecoder getDecoder(IoSession arg0)
throws Exception{
// TODO Auto-generated method stub
return decode;
}
@Override
public ProtocolEncoder getEncoder(IoSession arg0)
throws Exception{
// TODO Auto-generated method stub
return encode;
}
}
package com.cat.mina;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
public class MinaTextDecode implements ProtocolDecoder{
@Override
public void decode(IoSession session,
IoBuffer in,
ProtocolDecoderOutput out)
throws Exception{
int start = in.position();
while(in.hasRemaining()){
byte b = in.get();
if(b == '\n'){
//遇到換行之后就是一行
int current = in.position();
int limit = in.limit();
in.position(start);
in.limit(current);
IoBuffer buf = in.slice();
byte[] dest = new byte[buf.limit()];
buf.get(dest);
String str = new String(dest);
out.write(str);
in.position(current);
in.limit(limit);
}
}
}
@Override
public void dispose(IoSession arg0)
throws Exception{
// TODO Auto-generated method stub
}
@Override
public void finishDecode(IoSession arg0,
ProtocolDecoderOutput arg1)
throws Exception{
// TODO Auto-generated method stub
}
}
package com.cat.mina;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
public class MinaTextEncode implements ProtocolEncoder{
@Override
public void dispose(IoSession arg0)
throws Exception{
// TODO Auto-generated method stub
}
@Override
public void encode(IoSession session,
Object arg1,
ProtocolEncoderOutput out)
throws Exception{
String s= null;
if(arg1 instanceof String){
s = (String) arg1;
}
if(s != null){
CharsetEncoder charsetEncoder = (CharsetEncoder)session.getAttribute("encoder");
if(null == charsetEncoder){
charsetEncoder = Charset.defaultCharset().newEncoder();
session.setAttribute("encoder",charsetEncoder);
}
IoBuffer ioBuffer = IoBuffer.allocate(s.length());
ioBuffer.setAutoExpand(true);
ioBuffer.putString(s, charsetEncoder);
ioBuffer.flip();
out.write(ioBuffer);
}
}
}
最重要的是 HANDER类
package com.cat.mina;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import com.cat.common.json.RJson;
import com.cat.common.lang.RString;
public class MinaServerHandler implements IoHandler{
private static final Logger log = Logger.getLogger(MinaServerHandler.class);
public static Map<String, IoSession> map = new HashMap<String, IoSession>();
public static String User_Name = "userName";
@Override
public void exceptionCaught(IoSession arg0,
Throwable arg1)
throws Exception{
System.out.println("exceptionCaught");
// TODO Auto-generated method stub
}
@Override
public void inputClosed(IoSession arg0)
throws Exception{
System.out.println("inputClosed");
// TODO Auto-generated method stub
}
@Override
public void messageReceived(IoSession session,
Object arg1)
throws Exception{
String d = (String)arg1;
System.out.println("messageReceived:"+d);
Map<String, Object> m = null;
try{
m = RJson.parseJson2Map(d);
}catch(Exception e){
e.printStackTrace();
}
if(null != m){
String type = RString.toString(m.get("type"));
if("register".equalsIgnoreCase(type)){
//注册
String userName = RString.toString(m.get("userName"));
if(RString.isBlank(userName)){
sendMsgToClient(session, "register need userName,but is null");
return;
}
session.setAttribute(User_Name, userName);
map.put(userName, session);
sendMsgToClient(session, "register success");
return;
}else if("sendMsg".equalsIgnoreCase(type)){
String msg = RString.toString(m.get("msg"));
String to = RString.toString(m.get("to"));
sendMsgToOtherClient(session, to, msg);
}
}
}
public static void sendMsgToOtherClient(IoSession session,String to,
String msg){
IoSession toSession = map.get(to);
if(null == toSession){
sendMsgToClient(session,"is not online");
return;
}
sendMsgToClient(toSession,msg);
sendMsgToClient(session,"msg send Ok");
}
public static void sendMsgToClient(IoSession session,
String msg){
session.write(msg+"\n");
}
@Override
public void messageSent(IoSession arg0,
Object arg1)
throws Exception{
System.out.println("messageSent");
}
@Override
public void sessionClosed(IoSession arg0)
throws Exception{
System.out.println("sessionClosed");
}
@Override
public void sessionCreated(IoSession session)
throws Exception{
log.info("IoSession created address="+session.getRemoteAddress());
System.out.println("sessionCreated");
}
@Override
public void sessionIdle(IoSession arg0,
IdleStatus arg1)
throws Exception{
System.out.println("sessionIdle");
}
@Override
public void sessionOpened(IoSession arg0)
throws Exception{
System.out.println("sessionOpened");
}
}
客户端
package com.luoy;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class SocketClient{
public static void main(String[] args){
SocketClient cliCllient = new SocketClient();
cliCllient.start();
}
public void start(){
BufferedReader inputReader = null;
BufferedReader socketReder = null;
BufferedWriter write = null;
Socket socket = null;
try{
socket = new Socket("192.168.2.77", 5222);
write = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
socketReder = new BufferedReader(new InputStreamReader(socket.getInputStream()));
inputReader = new BufferedReader(new InputStreamReader(System.in));
startServerRead(socketReder);
String str;
while(!(str = inputReader.readLine()).equalsIgnoreCase("bye")){
write.write(str+"\n");
write.flush();
}
System.out.println("end");
}catch(IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
socket.close();
write.close();
inputReader.close();
socketReder.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void startServerRead(final BufferedReader read){
new Thread(new Runnable() {
@Override
public void run() {
String response = null;
try {
while((response = read.readLine()) != null){
System.out.println("client get msg:"+response);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
开启2个客户端之后,就能实现对话了