JAVA实现长连接(含心跳检测Demo)
实现原理:
长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的。
如果,长时间未发送维持连接包,服务端程序将断开连接。
客户端:
Client通过持有Socket的对象,可以随时(使用sendObject方法)发送MassageObject(消息)给服务端。
如果keepAliveDelay毫秒(程序中是2秒)内未发送任何数据,则自动发送一个KeepAliveObject(心跳)给服务端,用于维持连接。
由于,我们向服务端,可以发送很多不同的消息对象,服务端也可以返回不同的对象。所以,对于返回对象的处理,要编写具体的ObjectAction实现类进行处理。通过Client.addActionMap方法进行添加。这样,程序会回调处理。
服务端:
由于客户端会定时(keepAliveDelay毫秒)发送维持连接的信息过来,所以,服务端要有一个检测机制。
即当服务端receiveTimeDelay毫秒(程序中是3秒)内未接收任何数据,则自动断开与客户端的连接。
ActionMapping的原理与客户端相似(相同)。
通过添加相应的ObjectAction实现类,可以实现不同对象的响应、应答过程。
Demo:
packagesocket.keepalive.test; importjava.io.Serializable; importjava.text.SimpleDateFormat; importjava.util.Date; /** * *维持连接的消息对象(心跳对象) */ publicclassKeepAliveimplementsSerializable{ privatestaticfinallongserialVersionUID=-2813120366138988480L; /*覆盖该方法,仅用于测试使用。 *@seejava.lang.Object#toString() */ @Override publicStringtoString(){ returnnewSimpleDateFormat("yyyy-MM-ddHH:mm:ss").format(newDate())+"\t维持连接包"; } }
packagesocket.keepalive.test; importjava.io.IOException; importjava.io.InputStream; importjava.io.ObjectInputStream; importjava.io.ObjectOutputStream; importjava.net.Socket; importjava.net.UnknownHostException; importjava.util.Collections; importjava.util.concurrent.ConcurrentHashMap; /** *C/S架构的客户端对象,持有该对象,可以随时向服务端发送消息。 **创建时间:2010-7-18上午12:17:25 *@authorHouLei *@since1.0 */ publicclassClient{ /** *处理服务端发回的对象,可实现该接口。 */ publicstaticinterfaceObjectAction{ voiddoAction(Objectobj,Clientclient); } publicstaticfinalclassDefaultObjectActionimplementsObjectAction{ publicvoiddoAction(Objectobj,Clientclient){ System.out.println("处理:\t"+obj.toString()); } } publicstaticvoidmain(String[]args)throwsUnknownHostException,IOException{ StringserverIp="127.0.0.1"; intport=65432; Clientclient=newClient(serverIp,port); client.start(); } privateStringserverIp; privateintport; privateSocketsocket; privatebooleanrunning=false;//连接状态 privatelonglastSendTime;//最后一次发送数据的时间 //用于保存接收消息对象类型及该类型消息处理的对象 privateConcurrentHashMap
actionMapping=newConcurrentHashMap (); publicClient(StringserverIp,intport){ this.serverIp=serverIp; this.port=port; } publicvoidstart()throwsUnknownHostException,IOException{ if(running)return; socket=newSocket(serverIp,port); System.out.println("本地端口:"+socket.getLocalPort()); lastSendTime=System.currentTimeMillis(); running=true; newThread(newKeepAliveWatchDog()).start();//保持长连接的线程,每隔2秒项服务器发一个一个保持连接的心跳消息 newThread(newReceiveWatchDog()).start();//接受消息的线程,处理消息 } publicvoidstop(){ if(running)running=false; } /** *添加接收对象的处理对象。 *@paramcls待处理的对象,其所属的类。 *@paramaction处理过程对象。 */ publicvoidaddActionMap(Class
packagesocket.keepalive.test; importjava.io.IOException; importjava.io.InputStream; importjava.io.ObjectInputStream; importjava.io.ObjectOutputStream; importjava.net.ServerSocket; importjava.net.Socket; importjava.util.concurrent.ConcurrentHashMap; /** *C/S架构的服务端对象。 **创建时间:2010-7-18上午12:17:37 *@authorHouLei *@since1.0 */ publicclassServer{ /** *要处理客户端发来的对象,并返回一个对象,可实现该接口。 */ publicinterfaceObjectAction{ ObjectdoAction(Objectrev,Serverserver); } publicstaticfinalclassDefaultObjectActionimplementsObjectAction{ publicObjectdoAction(Objectrev,Serverserver){ System.out.println("处理并返回:"+rev); returnrev; } } publicstaticvoidmain(String[]args){ intport=65432; Serverserver=newServer(port); server.start(); } privateintport; privatevolatilebooleanrunning=false; privatelongreceiveTimeDelay=3000; privateConcurrentHashMap
actionMapping=newConcurrentHashMap (); privateThreadconnWatchDog; publicServer(intport){ this.port=port; } publicvoidstart(){ if(running)return; running=true; connWatchDog=newThread(newConnWatchDog()); connWatchDog.start(); } @SuppressWarnings("deprecation") publicvoidstop(){ if(running)running=false; if(connWatchDog!=null)connWatchDog.stop(); } publicvoidaddActionMap(Class
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。