一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java如何實現長連接

Java如何實現長連接

2020-09-09 00:25崔笑顏 Java教程

這篇文章主要介紹了Java如何實現長連接,幫助大家更好的理解和學習Java,感興趣的朋友可以了解下

實現原理:

長連接的維持,是要客戶端程序,定時向服務端程序,發送一個維持連接包的。
如果,長時間未發送維持連接包,服務端程序將斷開連接。

客戶端:

Client通過持有Socket的對象,可以隨時(使用sendObject方法)發送Massage Object(消息)給服務端。
如果keepAliveDelay毫秒(程序中是2秒)內未發送任何數據,則自動發送一個KeepAlive Object(心跳)給服務端,用于維持連接。
由于,我們向服務端,可以發送很多不同的消息對象,服務端也可以返回不同的對象。所以,對于返回對象的處理,要編寫具體的ObjectAction實現類進行處理。通過Client.addActionMap方法進行添加。這樣,程序會回調處理。

服務端:

由于客戶端會定時(keepAliveDelay毫秒)發送維持連接的信息過來,所以,服務端要有一個檢測機制。
即當服務端receiveTimeDelay毫秒(程序中是3秒)內未接收任何數據,則自動斷開與客戶端的連接。
ActionMapping的原理與客戶端相似(相同)。
通過添加相應的ObjectAction實現類,可以實現不同對象的響應、應答過程。

心跳反映的代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.java.excel.keepalive;
 
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
    *
    * 維持連接的消息對象(心跳對象)
    */
public class KeepAlive implements Serializable {
 
  private static final long serialVersionUID = -2813120366138988480L;
 
  /* 覆蓋該方法,僅用于測試使用。
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"\t維持連接包";
  }
 
}

服務端

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package com.java.excel.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;
 
public class Server {
 
  /**
   * 要處理客戶端發來的對象,并返回一個對象,可實現該接口。
   */
  public interface ObjectAction{
    Object doAction(Object rev, Server server);
  }
  
  public static final class DefaultObjectAction implements ObjectAction{
    public Object doAction(Object rev,Server server) {
      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<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();
  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<Object> 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,Server.this);
              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());
    }
    
  }
  
}

客戶端

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package com.java.excel.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;
 
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<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>();
  
  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(); //保持長連接的線程,每隔2秒項服務器發一個一個保持連接的心跳消息
    new Thread(new ReceiveWatchDog()).start();  //接受消息的線程,處理消息
  }
  
  public void stop(){
    if(running)running=false;
  }
  
  /**
   * 添加接收對象的處理對象。
   * @param cls 待處理的對象,其所屬的類。
   * @param action 處理過程對象。
   */
  public void addActionMap(Class<Object> 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 = 1000;
    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();
        }
      }
    }
  }
  
}

Java如何實現長連接

以上就是Java如何實現長連接的詳細內容,更多關于java實現長連接的資料請關注服務器之家其它相關文章!

原文鏈接:https://cloud.tencent.com/developer/article/1640058

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲国产精品牛在线 | 天选之王漫画顾长歌免费阅读 | 国产麻豆剧果冻传媒影视4934 | 久久婷婷丁香五月色综合啪免费 | 冰雪奇缘1完整版免费观看 变形金刚第一部 | 暖暖视频免费观看视频中国.韩剧 | 美女靠逼的视频 | 欧美灰丝袜丝交nylons | 草莓秋葵菠萝蜜绿巨人污 | 男神插曲女生动漫完整版动漫 | 免费观看在线 | 和两个男人玩3p好爽视频 | 国产99热 | 日本高清在线播放 | 天天狠天天透天干天天怕处 | 韩国三级hd中文字幕李采潭 | 成人免费播放 | 日韩精品一区二区三区中文在线 | 亚洲精品国产成人7777 | 亚洲精品国产SUV | 思思玖玖 | 成人区精品一区二区毛片不卡 | 国产精品第1页在线播放 | h版欧美大片免费观看 | 福利片免费一区二区三区 | 91碰 | 黑人干亚洲人 | 激情综合色啪啪小说 | 日本漫画大全之工之口 | www.久久99| 精品视频入口 | 国产小视频网站 | 成人操| 男人天堂a| 紧身短裙女教师波多野 | 精品无人乱码一区二区三区 | 欧美高清国产 | 大学生初次破苞免费视频 | 91免费精品国自产拍在线可以看 | 日韩免费在线观看 | 狠狠燥|