A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Jero 中级黑马   /  2014-5-14 23:38  /  1518 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 Jero 于 2014-5-17 22:46 编辑

Socket通信如何实现长连接?
长连接和断链接有什么区别?
区别在哪里?

4 个回复

正序浏览
大致解释一下什么意思:
长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的。
如果,长时间未发送维持连接包,服务端程序将断开连接。

客户端:
通过持有Client对象,可以随时(使用sendObject方法)发送Object给服务端。
如果keepAliveDelay毫秒(程序中是2秒)内未发送任何数据,则,自动发送一个KeepAlive对象给服务端,
用于维持连接。
由于,我们向服务端,可以发送很多不同的对象,服务端也可以返回不同的对象。
所以,对于返回对象的处理,要编写具体的ObjectAction实现类进行处理。
通过Client.addActionMap方法进行添加。这样,程序会回调处理。

服务端:
由于客户端会定时(keepAliveDelay毫秒)发送维持连接的信息过来,所以,服务端要有一个检测机制。
即当服务端receiveTimeDelay毫秒(程序中是3秒)内未接收任何数据,则,自动断开与客户端的连接。
ActionMapping的原理与客户端相似(相同)。
通过添加相应的ObjectAction实现类,可以实现不同对象的响应、应答过程。
回复 使用道具 举报
  1. package houlei.csdn.keepalive;


  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.ObjectInputStream;
  5. import java.io.ObjectOutputStream;
  6. import java.net.ServerSocket;
  7. import java.net.Socket;
  8. import java.util.concurrent.ConcurrentHashMap;

  9. /**
  10. * C/S架构的服务端对象。
  11. * <p>
  12. * 创建时间:2010-7-18 上午12:17:37
  13. * @author HouLei
  14. * @since 1.0
  15. */
  16. public class Server {

  17.         /**
  18.          * 要处理客户端发来的对象,并返回一个对象,可实现该接口。
  19.          */
  20.         public interface ObjectAction{
  21.                 Object doAction(Object rev);
  22.         }
  23.        
  24.         public static final class DefaultObjectAction implements ObjectAction{
  25.                 public Object doAction(Object rev) {
  26.                         System.out.println("处理并返回:"+rev);
  27.                         return rev;
  28.                 }
  29.         }
  30.        
  31.         public static void main(String[] args) {
  32.                 int port = 65432;
  33.                 Server server = new Server(port);
  34.                 server.start();
  35.         }
  36.        
  37.         private int port;
  38.         private volatile boolean running=false;
  39.         private long receiveTimeDelay=3000;
  40.         private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();
  41.         private Thread connWatchDog;
  42.        
  43.         public Server(int port) {
  44.                 this.port = port;
  45.         }

  46.         public void start(){
  47.                 if(running)return;
  48.                 running=true;
  49.                 connWatchDog = new Thread(new ConnWatchDog());
  50.                 connWatchDog.start();
  51.         }
  52.        
  53.         @SuppressWarnings("deprecation")
  54.         public void stop(){
  55.                 if(running)running=false;
  56.                 if(connWatchDog!=null)connWatchDog.stop();
  57.         }
  58.        
  59.         public void addActionMap(Class<Object> cls,ObjectAction action){
  60.                 actionMapping.put(cls, action);
  61.         }
  62.        
  63.         class ConnWatchDog implements Runnable{
  64.                 public void run(){
  65.                         try {
  66.                                 ServerSocket ss = new ServerSocket(port,5);
  67.                                 while(running){
  68.                                         Socket s = ss.accept();
  69.                                         new Thread(new SocketAction(s)).start();
  70.                                 }
  71.                         } catch (IOException e) {
  72.                                 e.printStackTrace();
  73.                                 Server.this.stop();
  74.                         }
  75.                        
  76.                 }
  77.         }
  78.        
  79.         class SocketAction implements Runnable{
  80.                 Socket s;
  81.                 boolean run=true;
  82.                 long lastReceiveTime = System.currentTimeMillis();
  83.                 public SocketAction(Socket s) {
  84.                         this.s = s;
  85.                 }
  86.                 public void run() {
  87.                         while(running && run){
  88.                                 if(System.currentTimeMillis()-lastReceiveTime>receiveTimeDelay){
  89.                                         overThis();
  90.                                 }else{
  91.                                         try {
  92.                                                 InputStream in = s.getInputStream();
  93.                                                 if(in.available()>0){
  94.                                                         ObjectInputStream ois = new ObjectInputStream(in);
  95.                                                         Object obj = ois.readObject();
  96.                                                         lastReceiveTime = System.currentTimeMillis();
  97.                                                         System.out.println("接收:\t"+obj);
  98.                                                         ObjectAction oa = actionMapping.get(obj.getClass());
  99.                                                         oa = oa==null?new DefaultObjectAction():oa;
  100.                                                         Object out = oa.doAction(obj);
  101.                                                         if(out!=null){
  102.                                                                 ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
  103.                                                                 oos.writeObject(out);
  104.                                                                 oos.flush();
  105.                                                         }
  106.                                                 }else{
  107.                                                         Thread.sleep(10);
  108.                                                 }
  109.                                         } catch (Exception e) {
  110.                                                 e.printStackTrace();
  111.                                                 overThis();
  112.                                         }
  113.                                 }
  114.                         }
  115.                 }
  116.                
  117.                 private void overThis() {
  118.                         if(run)run=false;
  119.                         if(s!=null){
  120.                                 try {
  121.                                         s.close();
  122.                                 } catch (IOException e) {
  123.                                         e.printStackTrace();
  124.                                 }
  125.                         }
  126.                         System.out.println("关闭:"+s.getRemoteSocketAddress());
  127.                 }
  128.                
  129.         }
  130.        
  131. }
复制代码
回复 使用道具 举报
  1. package houlei.csdn.keepalive;

  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.ObjectInputStream;
  5. import java.io.ObjectOutputStream;
  6. import java.net.Socket;
  7. import java.net.UnknownHostException;
  8. import java.util.concurrent.ConcurrentHashMap;

  9. /**
  10. *        C/S架构的客户端对象,持有该对象,可以随时向服务端发送消息。
  11. * <p>
  12. * 创建时间:2010-7-18 上午12:17:25
  13. * @author HouLei
  14. * @since 1.0
  15. */
  16. public class Client {

  17.         /**
  18.          * 处理服务端发回的对象,可实现该接口。
  19.          */
  20.         public static interface ObjectAction{
  21.                 void doAction(Object obj,Client client);
  22.         }
  23.         public static final class DefaultObjectAction implements ObjectAction{
  24.                 public void doAction(Object obj,Client client) {
  25.                         System.out.println("处理:\t"+obj.toString());
  26.                 }
  27.         }
  28.         public static void main(String[] args) throws UnknownHostException, IOException {
  29.                 String serverIp = "127.0.0.1";
  30.                 int port = 65432;
  31.                 Client client = new Client(serverIp,port);
  32.                 client.start();
  33.         }
  34.        
  35.         private String serverIp;
  36.         private int port;
  37.         private Socket socket;
  38.         private boolean running=false;
  39.         private long lastSendTime;
  40.         private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();
  41.        
  42.         public Client(String serverIp, int port) {
  43.                 this.serverIp=serverIp;this.port=port;
  44.         }
  45.        
  46.         public void start() throws UnknownHostException, IOException {
  47.                 if(running)return;
  48.                 socket = new Socket(serverIp,port);
  49.                 System.out.println("本地端口:"+socket.getLocalPort());
  50.                 lastSendTime=System.currentTimeMillis();
  51.                 running=true;
  52.                 new Thread(new KeepAliveWatchDog()).start();
  53.                 new Thread(new ReceiveWatchDog()).start();
  54.         }
  55.        
  56.         public void stop(){
  57.                 if(running)running=false;
  58.         }
  59.        
  60.         /**
  61.          * 添加接收对象的处理对象。
  62.          * @param cls 待处理的对象,其所属的类。
  63.          * @param action 处理过程对象。
  64.          */
  65.         public void addActionMap(Class<Object> cls,ObjectAction action){
  66.                 actionMapping.put(cls, action);
  67.         }

  68.         public void sendObject(Object obj) throws IOException {
  69.                 ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
  70.                 oos.writeObject(obj);
  71.                 System.out.println("发送:\t"+obj);
  72.                 oos.flush();
  73.         }
  74.        
  75.         class KeepAliveWatchDog implements Runnable{
  76.                 long checkDelay = 10;
  77.                 long keepAliveDelay = 2000;
  78.                 public void run() {
  79.                         while(running){
  80.                                 if(System.currentTimeMillis()-lastSendTime>keepAliveDelay){
  81.                                         try {
  82.                                                 Client.this.sendObject(new KeepAlive());
  83.                                         } catch (IOException e) {
  84.                                                 e.printStackTrace();
  85.                                                 Client.this.stop();
  86.                                         }
  87.                                         lastSendTime = System.currentTimeMillis();
  88.                                 }else{
  89.                                         try {
  90.                                                 Thread.sleep(checkDelay);
  91.                                         } catch (InterruptedException e) {
  92.                                                 e.printStackTrace();
  93.                                                 Client.this.stop();
  94.                                         }
  95.                                 }
  96.                         }
  97.                 }
  98.         }
  99.        
  100.         class ReceiveWatchDog implements Runnable{
  101.                 public void run() {
  102.                         while(running){
  103.                                 try {
  104.                                         InputStream in = socket.getInputStream();
  105.                                         if(in.available()>0){
  106.                                                 ObjectInputStream ois = new ObjectInputStream(in);
  107.                                                 Object obj = ois.readObject();
  108.                                                 System.out.println("接收:\t"+obj);
  109.                                                 ObjectAction oa = actionMapping.get(obj.getClass());
  110.                                                 oa = oa==null?new DefaultObjectAction():oa;
  111.                                                 oa.doAction(obj, Client.this);
  112.                                         }else{
  113.                                                 Thread.sleep(10);
  114.                                         }
  115.                                 } catch (Exception e) {
  116.                                         e.printStackTrace();
  117.                                         Client.this.stop();
  118.                                 }
  119.                         }
  120.                 }
  121.         }
  122.        
  123. }
复制代码
回复 使用道具 举报
本帖最后由 Jero 于 2014-5-17 22:43 编辑

  1. package houlei.csdn.keepalive;

  2. import java.io.Serializable;
  3. import java.text.SimpleDateFormat;
  4. import java.util.Date;

  5. /**
  6. * 维持连接的消息对象。
  7. * <p>
  8. * 创建时间:2010-7-18 上午12:22:09
  9. * @author HouLei
  10. * @since 1.0
  11. */
  12. public class KeepAlive implements Serializable{

  13.     private static final long serialVersionUID = -2813120366138988480L;

  14.     /* 覆盖该方法,仅用于测试使用。
  15.      * @see java.lang.Object#toString()
  16.      */
  17.     @Override
  18.     public String toString() {
  19.         return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"\t维持连接包";
  20.     }

  21. }
复制代码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马