一、基本原理
长连接、短连接 长连接比如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]