java长连接_java如何实现http长连接
java长连接_java如何实现http长连接
当年话下
通过轮询来实现长连接轮询:隔一段时间访问服务器,服务器不管有没有新消息都立刻返回。http长连接实现代码:客户端:package houlei.csdn.keepalive;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.Socket;import java.net.UnknownHostException;import java.util.concurrent.ConcurrentHashMap;/***C/S架构的客户端对象,持有该对象,可以随时向服务端发送消息。*
* 创建时间:2010-7-18 上午12:17:25* @author HouLei* @since 1.0*/public class Client {/*** 处理服务端发回的对象,可实现该接口。*/public static interface ObjectAction{void doAction(Object obj,Client client);}public static final class DefaultObjectAction implements ObjectAction{public void doAction(Object obj,Client client) {System.out.println("处理:\t"+obj.toString());//诊断程序是否正常}}public static void main(String[] args) throws UnknownHostException, IOException {String serverIp = "127.0.0.1";int port = 65432;Client client = new Client(serverIp,port);client.start();}private String serverIp;private int port;private Socket socket;private boolean running=false;private long lastSendTime;private ConcurrentHashMap actionMapping = new ConcurrentHashMap();public Client(String serverIp, int port) {this.serverIp=serverIp;this.port=port;}public void start() throws UnknownHostException, IOException {if(running)return;socket = new Socket(serverIp,port);System.out.println("本地端口:"+socket.getLocalPort());lastSendTime=System.currentTimeMillis();running=true;new Thread(new KeepAliveWatchDog()).start();new Thread(new ReceiveWatchDog()).start();}public void stop(){if(running)running=false;}/*** 添加接收对象的处理对象。* @param cls 待处理的对象,其所属的类。* @param action 处理过程对象。*/public void addActionMap(Class cls,ObjectAction action){actionMapping.put(cls, action);}public void sendObject(Object obj) throws IOException {ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());oos.writeObject(obj);System.out.println("发送:\t"+obj);oos.flush();}class KeepAliveWatchDog implements Runnable{long checkDelay = 10;long keepAliveDelay = 2000;public void run() {while(running){if(System.currentTimeMillis()-lastSendTime>keepAliveDelay){try {Client.this.sendObject(new KeepAlive());} catch (IOException e) {e.printStackTrace();Client.this.stop();}lastSendTime = System.currentTimeMillis();}else{try {Thread.sleep(checkDelay);} catch (InterruptedException e) {e.printStackTrace();Client.this.stop();}}}}}class ReceiveWatchDog implements Runnable{public void run() {while(running){try {InputStream in = socket.getInputStream();if(in.available()>0){ObjectInputStream ois = new ObjectInputStream(in);Object obj = ois.readObject();System.out.println("接收:\t"+obj);//接受数据ObjectAction oa = actionMapping.get(obj.getClass());oa = oa==null?new DefaultObjectAction():oa;oa.doAction(obj, Client.this);}else{Thread.sleep(10);}} catch (Exception e) {e.printStackTrace();Client.this.stop();}}}}}服务端:package houlei.csdn.keepalive;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.concurrent.ConcurrentHashMap;/*** C/S架构的服务端对象。*
* 创建时间:2010-7-18 上午12:17:37* @author HouLei* @since 1.0*/public class Server {/*** 要处理客户端发来的对象,并返回一个对象,可实现该接口。*/public interface ObjectAction{Object doAction(Object rev);}public static final class DefaultObjectAction implements ObjectAction{public Object doAction(Object rev) {System.out.println("处理并返回:"+rev);//确认长连接状况return rev;}}public static void main(String[] args) {int port = 65432;Server server = new Server(port);server.start();}private int port;private volatile boolean running=false;private long receiveTimeDelay=3000;private ConcurrentHashMap actionMapping = new ConcurrentHashMap();private Thread connWatchDog;public Server(int port) {this.port = port;}public void start(){if(running)return;running=true;connWatchDog = new Thread(new ConnWatchDog());connWatchDog.start();}@SuppressWarnings("deprecation")public void stop(){if(running)running=false;if(connWatchDog!=null)connWatchDog.stop();}public void addActionMap(Class cls,ObjectAction action){actionMapping.put(cls, action);}class ConnWatchDog implements Runnable{public void run(){try {ServerSocket ss = new ServerSocket(port,5);while(running){Socket s = ss.accept();new Thread(new SocketAction(s)).start();}} catch (IOException e) {e.printStackTrace();Server.this.stop();}}}class SocketAction implements Runnable{Socket s;boolean run=true;long lastReceiveTime = System.currentTimeMillis();public SocketAction(Socket s) {this.s = s;}public void run() {while(running && run){if(System.currentTimeMillis()-lastReceiveTime>receiveTimeDelay){overThis();}else{try {InputStream in = s.getInputStream();if(in.available()>0){ObjectInputStream ois = new ObjectInputStream(in);Object obj = ois.readObject();lastReceiveTime = System.currentTimeMillis();System.out.println("接收:\t"+obj);ObjectAction oa = actionMapping.get(obj.getClass());oa = oa==null?new DefaultObjectAction():oa;Object out = oa.doAction(obj);if(out!=null){ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());oos.writeObject(out);oos.flush();}}else{Thread.sleep(10);}} catch (Exception e) {e.printStackTrace();overThis();}}}}private void overThis() {if(run)run=false;if(s!=null){try {s.close();} catch (IOException e) {e.printStackTrace();}}System.out.println("关闭:"+s.getRemoteSocketAddress());//关闭长连接}}}长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的。如果,长时间未发送维持连接包,服务端程序将断开连接。