推送服务器
一、基本原理
长连接、短连接 长连接比如socket,短连接比如HTTP
短连接推送就是不断的客户端向服务器轮训;长连接推送就是服务器的推送(本文)
考虑的问题诸如身份鉴别认证、服务器并发量、断线重连
二、使用Socket和Mina框架
【Server】Server要先于Client启动
ServerSocket serverSock = new ServerSocket("9898"); Socket socket = serverSock.accept();//block here BufferedReader buffer = new BufferReader(new InputStreamReader(socket.getInputStream())); String msg; while(!msg = buffer.readLine() != null){//必须有个\n System.out.println() } //close the stream object
【Client】
BufferedReader inputReader; BufferedWriter writer; try{ Socket socket = new Socket("localhost", "9898");//client socket writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); inputReader = new BufferReader(new InputStreamReader(System.in));//从控制台获取字符串 String inputContent; while(!(inputContent = inputReader.readLine().equals("bye"))){ writer.write(inputContent + "\n");//必须有个\n writer.flush(); } }catch(Exception e){ }finally{ //close stream }
【客户端异步的监听服务器发送过来的消息】
匿名内部类在方法内部时,方法的参数必须要用final修饰,保证传进来的变量内外一致性
public void startServerReplyListener(final BufferedReader reader){ new Thread( new Runnable(){ public void run(){ String response; while(response = reader.readLine() != null){//阻塞 //do something } } } ).start(); }
//调用
startServerReplyListener(new BufferReader(new InputStreamReader(socket.getInputStream())));
Server中用while(true)来死循环接收客户的连接,同时开启新的子线程处理与客户端的交互
public void managerSock(final Socket socket){ new Thread( new Runnable(){ public void run(){ BufferedReader buffer = new BufferReader(new InputStreamReader(socket.getInputStream())); String msg; while(!msg = buffer.readLine() != null){//必须有个\n System.out.println() } } } ).start(); } //在主线程中 while(true){ Socket clientSocket = Server.accept(); managerSock(clientSocket); }
若有大量客户连接的时候,因为有大量线程的创建,因为性能问题,很少会有用原生的Socket接口,同时因为是阻塞的接口,所以会有性能问题。
所以可以用NIO的框架Mina
【Mina初体验】
两个使用的jar包:mina-core.jar,slf4j-api.jar(打印日志用)
四步骤来创建一个Mina Server
a. new NioSocketAcceptor
b. 使用一个handler继承IoHandlerAdapter作为回话管理和消息分发机制,放到acceptor里面
c. 使用拦截器过滤来编解码,做onMessageRecieve收回的message的对象的转换工作,声明想要接受的数据类型
d. 调用acceptor的bind方法//服务器启动起来了
创建以后就可以正常接受上述普通Socket客户端的连接请求和数据发送了
//设置idle的定义
acceptor.getSeeionConfig().setIdleTime(IdleStatus.xxx,seconds)
这个可以定义客户端多久没有发送或者读取消息的时候为空闲状态,那么这个时候IoHandlerAdapter的onSessionIdle会回调到
这个可以用于判定是否客户端是否掉线,如果客户端一定时间没哟连接,那么这个时候服务端可以选择踢掉客户端
【自定义编解码】
实现ProtocolCodecFactory接口,其中复写两个方法,分别返回加解密的对象
【XMPP协议】
XMPP是一种以XML为基础的开放式实时通信协议,其实推送就是IM通信的“一半”
GTalk,MSN,Facebook都是支持XMPP协议
XMPP由于是基于XML,所以有数据冗余,在移动端会产生很多不必要的流量,但是由于推送并不频繁数据传输,所以不用考虑
同时不支持二进制数据。不过XMPP主要是关注与消息的传输
XMPP规定每个客户端使用JID来身份表示:[user"@"]domain["/"resource]