├── .gitignore
├── README.md
├── pom.xml
├── slice
├── ICommon.ice
└── ISwitch.ice
└── src
├── main
├── java
│ └── com
│ │ └── demo
│ │ └── tcp
│ │ ├── ice
│ │ └── impl
│ │ │ ├── SwitchCallbackI.java
│ │ │ └── SwitchI.java
│ │ ├── main
│ │ ├── Main.java
│ │ └── SwitchUtil.java
│ │ └── model
│ │ └── SwitchCallbackPrxCache.java
└── resources
│ ├── log4j.properties
│ └── syscfg.properties
└── test
├── java
└── com
│ └── demo
│ └── tcp
│ └── SwitchClient.java
└── resources
└── SwitchClient.conf
/.gitignore:
--------------------------------------------------------------------------------
1 | /generated/
2 | /target/
3 | /.settings/
4 | /.classpath
5 | /.project
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # demo_zeroc_ice_tcp
2 | Zeroc Ice TCP长连接 实现推送功能
3 |
4 | ## 参考
5 | http://blog.csdn.net/jerome_s/article/details/54092791
6 |
7 | ## 系统配置
8 | IDE:Eclipse
9 | ICE Library:ice-3.6.2.jar
10 |
11 | ## 运行例子步骤
12 | 1. 运行Main.java 启动服务端
13 | 里面有启动一个线程 二十秒后会往注册的客户端发送数据
14 | 2. 运行SwitchClient.java启动客户端对服务端进行心跳
15 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | com.demo
6 | tcp
7 | 0.0.1-SNAPSHOT
8 | jar
9 |
10 | tcp
11 | http://maven.apache.org
12 |
13 |
14 | UTF-8
15 |
16 |
17 |
18 |
19 | junit
20 | junit
21 | 3.8.1
22 | test
23 |
24 |
25 | org.slf4j
26 | slf4j-log4j12
27 | 1.7.7
28 |
29 |
30 | log4j
31 | log4j
32 | 1.2.17
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/slice/ICommon.ice:
--------------------------------------------------------------------------------
1 | module switcher
2 | {
3 | /**
4 | * SMHome所有接口类的共同父类
5 | */
6 | interface IBase
7 | {
8 |
9 | };
10 |
11 | /**
12 | * Switch异常,
13 | * 通过code区分不同的异常。
14 | */
15 | exception SwitchException
16 | {
17 | /**
18 | * 异常代码
19 | */
20 | int code;
21 | /**
22 | * 异常信息
23 | */
24 | string message;
25 | };
26 |
27 |
28 | /**
29 | * 基类:
30 | */
31 | class BaseInfo
32 | {
33 |
34 | };
35 |
36 | /**
37 | * 基类集合
38 | */
39 | ["java:type:java.util.ArrayList:java.util.ArrayList"]
40 | sequence < BaseInfo > BaseInfoSeq;
41 | };
42 |
--------------------------------------------------------------------------------
/slice/ISwitch.ice:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "ICommon.ice"
4 | module switcher
5 | {
6 | /**
7 | * 回调客户端接口定义(服务端调用客户端的接口)
8 | */
9 | interface ISwitchCallback
10 | {
11 | /**
12 | * 发送二进制数组
13 | * @param byteSeq 二进制数组
14 | * @return true/false
15 | */
16 | bool send(Ice::ByteSeq byteSeq) throws SwitchException;
17 |
18 | /**
19 | * 发送字符串
20 | * @param msg 字符串
21 | * @return true/false
22 | */
23 | bool sendMsg(string msg) throws SwitchException;
24 | };
25 |
26 | /**
27 | * 服务端接口定义(客户端调用服务端的接口)
28 | */
29 | interface ISwitch
30 | {
31 | /**
32 | * 对服务端进行心跳(无异常则表示成功)
33 | * @param sn 设备串号
34 | * @param netMode 网络接入方式 0:没有 1:3G 2:4G 3:以太网 4:wifi 5:2G
35 | * @param netStrength 网络信号强度
36 | */
37 | bool heartbeat(Ice::Identity id, string sn, int netMode, int netStrength) throws SwitchException;
38 |
39 | /**
40 | * 设备回调
41 | * @param byteSeq 二进制数组
42 | * @return true/false
43 | */
44 | bool callBack(string msg) throws SwitchException;
45 | };
46 | };
--------------------------------------------------------------------------------
/src/main/java/com/demo/tcp/ice/impl/SwitchCallbackI.java:
--------------------------------------------------------------------------------
1 | package com.demo.tcp.ice.impl;
2 |
3 | import org.apache.log4j.Logger;
4 |
5 | import Ice.Current;
6 | import switcher.SwitchException;
7 | import switcher._ISwitchCallbackDisp;
8 |
9 | /**
10 | * 回调客户端接口定义(服务端调用客户端的接口)
11 | *
12 | * @author jerome
13 | */
14 | public class SwitchCallbackI extends _ISwitchCallbackDisp {
15 |
16 | private static Logger LOGGER = Logger.getLogger(SwitchCallbackI.class);
17 | private static final long serialVersionUID = 1L;
18 |
19 | public SwitchCallbackI() {
20 | }
21 |
22 | @Override
23 | public boolean send(byte[] byteSeq, Current __current) throws SwitchException {
24 | // 客户端打印会打印以下信息
25 | LOGGER.info("send() byteSeq = " + new String(byteSeq));
26 | return true;
27 | }
28 |
29 | @Override
30 | public boolean sendMsg(String msg, Current __current) throws SwitchException {
31 | // 客户端打印会打印以下信息
32 | LOGGER.info("sendMsg() msg = " + msg);
33 | return true;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/demo/tcp/ice/impl/SwitchI.java:
--------------------------------------------------------------------------------
1 | package com.demo.tcp.ice.impl;
2 |
3 | import java.util.concurrent.ConcurrentHashMap;
4 |
5 | import org.apache.log4j.Logger;
6 |
7 | import com.demo.tcp.model.SwitchCallbackPrxCache;
8 |
9 | import Ice.Current;
10 | import Ice.Identity;
11 | import switcher.ISwitchCallbackPrx;
12 | import switcher.ISwitchCallbackPrxHelper;
13 | import switcher._ISwitchDisp;
14 |
15 | /**
16 | * 服务端接口定义(客户端调用服务端的接口)
17 | *
18 | * @author jerome
19 | */
20 | public class SwitchI extends _ISwitchDisp {
21 |
22 | private static Logger LOGGER = Logger.getLogger(SwitchI.class);
23 | private static final long serialVersionUID = 1L;
24 |
25 | // 客户端连接缓存 XXX 超时清除? Redis?
26 | public static ConcurrentHashMap switchCallbackPrxCacheMap = new ConcurrentHashMap<>();
27 | private SwitchCallbackPrxCache switchCallbackPrxCache = null;
28 |
29 | public SwitchI(Ice.Properties p) {
30 | }
31 |
32 | /**
33 | * 心跳(如果用户自己定时做心跳可以心跳时传参)
34 | */
35 | @Override
36 | public boolean heartbeat(Identity id, String sn, int netMode, int netStrength, Current current) {
37 | LOGGER.info(switchCallbackPrxCacheMap.size());
38 | LOGGER.info("tcp heartbeat begin params sn = " + sn + " id.name = " + id.name + ", category = " + id.category
39 | + ", netMode = " + netMode + ", netStrength = " + netStrength);
40 | Ice.Connection con = current.con;
41 | Ice.IPConnectionInfo ipConn = (Ice.IPConnectionInfo) con.getInfo();
42 | if (null != ipConn) {
43 | LOGGER.info("ipConn remote:" + ipConn.remoteAddress + ":" + ipConn.remotePort);
44 | LOGGER.info("ipConn local:" + ipConn.localAddress + ":" + ipConn.localPort);
45 | }
46 |
47 | LOGGER.info("heartbeat");
48 | // 心跳业务处理
49 |
50 | // 如果已经存在不更新缓存
51 | if (switchCallbackPrxCacheMap.containsKey(sn)) {
52 | SwitchCallbackPrxCache switchCallbackPrxCache = switchCallbackPrxCacheMap.get(sn);
53 | if (ipConn.remoteAddress.equals(switchCallbackPrxCache.getIp())
54 | && switchCallbackPrxCache.getPort() == ipConn.remotePort) {
55 | LOGGER.info("already exist cache, return true\n");
56 | return true;
57 | } else {
58 | switchCallbackPrxCacheMap.remove(sn);
59 | }
60 | }
61 |
62 | ISwitchCallbackPrx switchCallbackPrx = ISwitchCallbackPrxHelper.checkedCast(con.createProxy(id));
63 |
64 | switchCallbackPrxCache = new SwitchCallbackPrxCache();
65 | switchCallbackPrxCache.setiSwitchCallbackPrx(switchCallbackPrx);
66 | switchCallbackPrxCache.setIp(ipConn.remoteAddress);
67 | switchCallbackPrxCache.setPort(ipConn.remotePort);
68 |
69 | switchCallbackPrxCacheMap.put(sn, switchCallbackPrxCache);
70 | // 如果用户不是定时心跳,而是使用ice自带的心跳必须执行以下代码
71 | holdHeartbeat(current.con);
72 | LOGGER.info("register end, return true. \n");
73 |
74 | return true;
75 | }
76 |
77 | /**
78 | * ice自带保持心跳
79 | *
80 | * @author jerome
81 | * @param con
82 | */
83 | private void holdHeartbeat(Ice.Connection con) {
84 | con.setCallback(new Ice.ConnectionCallback() {
85 | @Override
86 | public void heartbeat(Ice.Connection c) {
87 | LOGGER.debug("service heartbeat...");
88 | }
89 |
90 | @Override
91 | public void closed(Ice.Connection c) {
92 | LOGGER.debug("service close!");
93 | }
94 | });
95 |
96 | // 每10/2 s向对方做心跳
97 | // 服务端向客户端做心跳 客户端打印客户端的con.setCallback(new Ice.ConnectionCallback()
98 | // con.setACM(new Ice.IntOptional(10), new Ice.Optional(Ice.ACMClose.CloseOff),
99 | // new Ice.Optional(Ice.ACMHeartbeat.HeartbeatAlways));
100 | }
101 |
102 | /**
103 | * 客户端可以回调这个接口
104 | */
105 | @Override
106 | public boolean callBack(String msg, Current current) {
107 |
108 | LOGGER.info("ice tcp callBack start. params msg = " + msg);
109 |
110 | boolean result = true;
111 |
112 | Ice.Connection con = current.con;
113 | Ice.IPConnectionInfo ipConn = (Ice.IPConnectionInfo) con.getInfo();
114 | if (null != ipConn) {
115 | LOGGER.info("ipConn remote:" + ipConn.remoteAddress + ":" + ipConn.remotePort);
116 | LOGGER.info("ipConn local:" + ipConn.localAddress + ":" + ipConn.localPort);
117 | }
118 |
119 | LOGGER.info("ice tcp callBack end. return result = " + result);
120 |
121 | return result;
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/src/main/java/com/demo/tcp/main/Main.java:
--------------------------------------------------------------------------------
1 | package com.demo.tcp.main;
2 |
3 | import java.io.File;
4 |
5 | import org.apache.log4j.Logger;
6 |
7 | import com.demo.tcp.ice.impl.SwitchI;
8 |
9 | /**
10 | * 启动服务端
11 | *
12 | * @author jerome
13 | */
14 | public class Main extends Ice.Application {
15 |
16 | private static String APP_MAIN = System.getenv("APP_HOME");
17 | private static String SIP_CONFIG = "../src/main/resources/syscfg.properties";
18 | private static Logger LOGGER = Logger.getLogger(Main.class);
19 |
20 | public static void main(String[] args) throws Exception {
21 |
22 | // 服务端发送数据给客户端 SwitchClient.java要运行
23 | new Thread(new Runnable() {
24 | @Override
25 | public void run() {
26 | LOGGER.info("send thread start.");
27 | try {
28 | Thread.sleep(30000);
29 | } catch (InterruptedException e) {
30 | e.printStackTrace();
31 | }
32 | // 和服务端心跳的标识
33 | String sn = "0481deb6494848488048578316516694";
34 | String msg = "test msg.";
35 | LOGGER.info("result = " + SwitchUtil.sendMsg(sn, msg));
36 | }
37 | }).start();
38 |
39 | // 启动ice
40 | LOGGER.info("===========starting ice service============");
41 | String confPath = SIP_CONFIG;
42 | if (null != APP_MAIN) {
43 | confPath = APP_MAIN + "/src/main/resources/syscfg.properties";
44 | } else {
45 | confPath = SIP_CONFIG;
46 | File file = new File(confPath);
47 | if (!file.exists()) {
48 | confPath = System.getProperty("user.dir") + "/src/main/resources/syscfg.properties";
49 | }
50 | }
51 | LOGGER.info("confPath=" + confPath);
52 |
53 | Main app = new Main();
54 |
55 | int status = app.main("Main", args, confPath);
56 | System.exit(status);
57 | }
58 |
59 | /*
60 | * server run
61 | *
62 | * @see Ice.Application#run(java.lang.String[])
63 | */
64 | public int run(String[] args) {
65 | if (args.length > 1) {
66 | LOGGER.info(appName() + ": too many arguments");
67 | LOGGER.info(appName() + ":");
68 | return 1;
69 | }
70 |
71 | Ice.ObjectAdapter adapter = communicator().createObjectAdapter("Switch");
72 | Ice.Properties p = communicator().getProperties();
73 |
74 | adapter.add(new SwitchI(p), communicator().stringToIdentity("Switch"));
75 | adapter.activate();
76 | LOGGER.info("ice is started!");
77 | communicator().waitForShutdown();
78 | return 0;
79 | }
80 | }
--------------------------------------------------------------------------------
/src/main/java/com/demo/tcp/main/SwitchUtil.java:
--------------------------------------------------------------------------------
1 | package com.demo.tcp.main;
2 |
3 | import org.apache.log4j.Logger;
4 |
5 | import com.demo.tcp.ice.impl.SwitchI;
6 |
7 | import switcher.ISwitchCallbackPrx;
8 | import switcher.SwitchException;
9 |
10 | public class SwitchUtil {
11 | private static Logger LOGGER = Logger.getLogger(SwitchUtil.class);
12 |
13 | /**
14 | * 发送数据
15 | *
16 | * @author jerome
17 | * @param sn
18 | * 和服务端心跳的标识
19 | * @param msg
20 | * 字符串
21 | * @return
22 | */
23 | public static boolean sendMsg(String sn, String msg) {
24 |
25 | LOGGER.info("ice tcp send params sn = " + sn);
26 |
27 | boolean sendResult = true;
28 |
29 | if (!SwitchI.switchCallbackPrxCacheMap.containsKey(sn)) {
30 | LOGGER.warn("PrxCacheMap is no exist, ice tcp send end, sendResult = false\n");
31 | return false;
32 | }
33 |
34 | ISwitchCallbackPrx switchCallbackPrx = SwitchI.switchCallbackPrxCacheMap.get(sn).getiSwitchCallbackPrx();
35 | if (null != switchCallbackPrx) {
36 | try {
37 | sendResult = switchCallbackPrx.sendMsg(msg);
38 | } catch (SwitchException e) {
39 | LOGGER.error(e.toString());
40 | e.printStackTrace();
41 | sendResult = false;
42 | }
43 | } else {
44 | sendResult = false;
45 | }
46 |
47 | LOGGER.info("ice tcp send end, sendResult = " + sendResult + "\n");
48 | LOGGER.info("sendResult = " + sendResult);
49 | return sendResult;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/demo/tcp/model/SwitchCallbackPrxCache.java:
--------------------------------------------------------------------------------
1 | package com.demo.tcp.model;
2 |
3 | import switcher.ISwitchCallbackPrx;
4 |
5 | /**
6 | * ice客户端缓存信息
7 | *
8 | * @author jerome
9 | */
10 | public class SwitchCallbackPrxCache {
11 |
12 | private ISwitchCallbackPrx iSwitchCallbackPrx;
13 | private String ip;
14 | private int port;
15 |
16 | public ISwitchCallbackPrx getiSwitchCallbackPrx() {
17 | return iSwitchCallbackPrx;
18 | }
19 |
20 | public void setiSwitchCallbackPrx(ISwitchCallbackPrx iSwitchCallbackPrx) {
21 | this.iSwitchCallbackPrx = iSwitchCallbackPrx;
22 | }
23 |
24 | public String getIp() {
25 | return ip;
26 | }
27 |
28 | public void setIp(String ip) {
29 | this.ip = ip;
30 | }
31 |
32 | public int getPort() {
33 | return port;
34 | }
35 |
36 | public void setPort(int port) {
37 | this.port = port;
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | ######log FATAL>error > warn > info > debug
2 | #log4j.rootLogger = [ level ] , appenderName, appenderName,
3 | log4j.rootLogger =debug,info,warn,debug,error,console
4 | #ERROR,console,warn,info,debug
5 | #log4j.logger.com.canal_web=debug
6 |
7 | log4j.appender.console=org.apache.log4j.ConsoleAppender
8 | log4j.appender.console.Target = System.out
9 | log4j.appender.console.layout=org.apache.log4j.PatternLayout
10 | log4j.appender.console.layout.ConversionPattern=%d %p [%c] - %m%n
11 |
12 | log4j.logger.debug=debug
13 | log4j.appender.debug=org.apache.log4j.RollingFileAppender
14 | log4j.appender.debug.File=d:/logs/lz/debug.log
15 | log4j.appender.debug.Threshold=debug
16 | log4j.appender.debug.layout=org.apache.log4j.PatternLayout
17 | log4j.appender.debug.layout.ConversionPattern=%d %p [%c] - <%m>%n
18 | log4j.appender.debug.MaxFileSize=30MB
19 | log4j.appender.debug.Append=true
20 | log4j.appender.debug.MaxBackupIndex=10
21 |
22 | log4j.logger.info=info
23 | log4j.appender.info=org.apache.log4j.RollingFileAppender
24 | log4j.appender.info.File=D:/info.log
25 | log4j.appender.info.Threshold=info
26 | log4j.appender.info.layout=org.apache.log4j.PatternLayout
27 | log4j.appender.info.layout.ConversionPattern=%d %p [%c] - <%m>%n
28 | #一个文件最大10M
29 | log4j.appender.info.MaxFileSize=10MB
30 | log4j.appender.info.Append=true
31 | #最多十个文件
32 | log4j.appender.info.MaxBackupIndex=10
33 |
34 | log4j.logger.warn=warn
35 | log4j.appender.warn=org.apache.log4j.RollingFileAppender
36 | log4j.appender.warn.File=D:/warn.log
37 | log4j.appender.warn.Threshold=WARN
38 | log4j.appender.warn.layout=org.apache.log4j.PatternLayout
39 | log4j.appender.warn.layout.ConversionPattern=%d %p [%c] - <%m>%n
40 | log4j.appender.warn.MaxFileSize=10MB
41 | log4j.appender.warn.Append=true
42 | log4j.appender.warn.MaxBackupIndex=10
43 |
44 | log4j.logger.error=error
45 | log4j.appender.error=org.apache.log4j.RollingFileAppender
46 | log4j.appender.error.File=D:/error.log
47 | log4j.appender.error.Threshold=error
48 | log4j.appender.error.layout=org.apache.log4j.PatternLayout
49 | log4j.appender.error.layout.ConversionPattern=%d %p [%c] - <%m>%n
50 | log4j.appender.error.MaxFileSize=10MB
51 | log4j.appender.error.Append=true
52 | log4j.appender.error.MaxBackupIndex=10
53 |
54 | #错误日志写入数据库
55 | log4j.appender.errordb=org.apache.log4j.jdbc.JDBCAppender
56 | log4j.appender.errordb.Threshold=error
57 | log4j.appender.errordb.driver=com.mysql.jdbc.Driver
58 | log4j.appender.errordb.URL=jdbc\:mysql\://123.0.0.1\:3306/test_db?useUnicode\=true&characterEncoding\=gbk&allowMultiQueries\=true&zeroDateTimeBehavior\=convertToNull
59 | log4j.appender.errordb.user=root
60 | log4j.appender.errordb.password=root
61 | log4j.appender.errordb.sql=insert into sys_log4j(log_tag, log_time, log_msg) VALUES ('app_name', '%d', '%p [%c] - <%m>%n')
62 | log4j.appender.errordb.layout=org.apache.log4j.PatternLayout
63 |
--------------------------------------------------------------------------------
/src/main/resources/syscfg.properties:
--------------------------------------------------------------------------------
1 | #
2 | # The server creates one single object adapter with the name
3 | # "Hello". The following line sets the endpoints for this
4 | # adapter.
5 | #
6 | Switch.Endpoints=tcp -h 127.0.0.1 -p 5010
7 |
8 | #
9 | # Warn about connection exceptions
10 | #
11 | Ice.Warn.Connections=1
12 |
13 |
14 | Ice.ThreadPool.Server.Size=2
15 | Ice.ThreadPool.Server.SizeMax=10
16 | Ice.ThreadPool.Server.SizeWarn=6
17 | #Ice.ThreadPool.Client.Size=1
18 | #Ice.ThreadPool.Client.SizeMax=30
19 | #Ice.ThreadPool.Client.SizeWarn=20
20 |
21 | #
22 | # Server-side ACM is disabled by default. For this demo, we want it
23 | # enabled and set to a short timeout of 10 seconds. By enabling
24 | # network tracing below, you can see ACM automatically close idle
25 | # connections.
26 | #
27 | #Ice.ACM.Server=10
28 |
29 | #Ice.MessageSizeMax=4096
30 |
31 |
32 | #Ice.RetryIntervals=0 100 500 1000
33 | #Ice.Trace.Retry=1
34 |
35 | #
36 | # Network Tracing
37 | #
38 | # 0 = no network tracing
39 | # 1 = trace connection establishment and closure
40 | # 2 = like 1, but more detailed
41 | # 3 = like 2, but also trace data transfer
42 | #
43 | Ice.Trace.Network=3
44 |
45 |
46 | Ice.Trace.ThreadPool=1
47 |
48 |
49 | #Ice.Override.ConnectTimeout=5000
50 | #Ice.Override.Timeout=50000
51 |
52 | #Ice.StdOut=./log/lzpush_ice.out
53 | #Ice.StdErr=./log/lzpush_ice.err
54 |
55 | #
56 | # Protocol Tracing
57 | #
58 | # 0 = no protocol tracing
59 | # 1 = trace protocol messages
60 | #
61 | #Ice.Trace.Protocol=1
62 |
--------------------------------------------------------------------------------
/src/test/java/com/demo/tcp/SwitchClient.java:
--------------------------------------------------------------------------------
1 | package com.demo.tcp;
2 |
3 | import java.io.File;
4 |
5 | import org.apache.log4j.Logger;
6 |
7 | import com.demo.tcp.ice.impl.SwitchCallbackI;
8 | import com.demo.tcp.main.Main;
9 |
10 | import Ice.Connection;
11 | import Ice.LocalException;
12 | import Ice.TCPConnectionInfo;
13 | import Ice.UserException;
14 | import switcher.Callback_ISwitch_heartbeat;
15 | import switcher.ISwitchPrx;
16 | import switcher.ISwitchPrxHelper;
17 |
18 | public class SwitchClient extends Ice.Application {
19 |
20 | private static Logger LOGGER = Logger.getLogger(Main.class);
21 | Ice.Communicator communicator = null;
22 | ISwitchPrx switchPushPrx = null;
23 |
24 | public String sn = "0481deb6494848488048578316516694";
25 | private String prxStr = "Switch:tcp -h 127.0.0.1 -p 5010";
26 |
27 | static String APP_MAIN = System.getenv("APP_HOME");
28 | static String PUSH_CLIENT_CONFIG = "/src/test/resources/SwitchClient.conf";
29 |
30 | public SwitchClient() {
31 | }
32 |
33 | public static void main(String[] args) {
34 |
35 | String confPath = PUSH_CLIENT_CONFIG;
36 | if (null != APP_MAIN)
37 | confPath = APP_MAIN + "/src/main/resources/syscfg.properties";
38 | else {
39 | confPath = PUSH_CLIENT_CONFIG;
40 | File file = new File(confPath);
41 | if (!file.exists()) {
42 | confPath = System.getProperty("user.dir") + "/src/test/resources/SwitchClient.conf";
43 | }
44 | }
45 |
46 | SwitchClient lpClient = new SwitchClient();
47 |
48 | int status = lpClient.main("SwitchClient", args, confPath);
49 |
50 | System.exit(status);
51 | }
52 |
53 | public int run(String[] args) {
54 | try {
55 | communicator = communicator();
56 | switchPushPrx = ISwitchPrxHelper.checkedCast(communicator.stringToProxy(prxStr));
57 | switchPushPrx.ice_ping();
58 | } catch (Ice.LocalException ex) {
59 | ex.printStackTrace();
60 | }
61 |
62 | Ice.ObjectAdapter adapter = communicator.createObjectAdapter("");
63 |
64 | Ice.Identity id = new Ice.Identity();
65 | id.category = "";
66 | id.name = "SwitchClient";
67 |
68 | adapter.add(new SwitchCallbackI(), id);
69 |
70 | adapter.activate();
71 |
72 | switchPushPrx.ice_getConnection().setAdapter(adapter);
73 |
74 | LOGGER.info("SwitchClient ice is started! " + "getEndpoint = "
75 | + switchPushPrx.ice_getConnection().getEndpoint()._toString());
76 |
77 | try {
78 | String ip = ""; // 缓存当前ip
79 | int port = 0; // 缓存当前端口
80 |
81 | while (true) {
82 |
83 | // ip或端口不一样时,重置适配器(服务端重启的情况)
84 | if (switchPushPrx == null) {
85 | break;
86 | }
87 |
88 | Connection connection = null;
89 | String localIp = null;
90 | int localPort = 0;
91 | try {
92 | connection = switchPushPrx.ice_getConnection();
93 | TCPConnectionInfo connectionInfo = (TCPConnectionInfo) connection.getInfo();
94 | localIp = connectionInfo.localAddress;
95 | localPort = connectionInfo.localPort;
96 | LOGGER.info("localIp:" + localIp + "; localPort:" + localPort);
97 | if (!ip.equals(localIp) || port != localPort) {
98 | ip = localIp;
99 | port = localPort;
100 | LOGGER.info("ip or port is change. set adapter.");
101 | connection.setAdapter(adapter);
102 | }
103 | } catch (Exception e) {
104 | e.printStackTrace();
105 | }
106 |
107 | LOGGER.info("SwitchClient is begin heartbeat.");
108 |
109 | // 使用异步的方式
110 | switchPushPrx.begin_heartbeat(id, sn, 1, 2, new Callback_ISwitch_heartbeat() {
111 |
112 | @Override
113 | public void exception(LocalException __ex) {
114 | }
115 |
116 | @Override
117 | public void response(boolean arg) {
118 | LOGGER.info("heartbeat result = " + arg);
119 | if (arg) {
120 | LOGGER.info("心跳成功");
121 | } else {
122 | LOGGER.info("心跳失败");
123 | }
124 | }
125 |
126 | @Override
127 | public void exception(UserException ex) {
128 | }
129 | });
130 |
131 | LOGGER.info("SwitchClient is end heartbeat.\n");
132 | Thread.sleep(5000);
133 | }
134 | // 可以使用以上的while(true)
135 | // Thread.sleep(HEARTBEAT_TIME);的方式定时请求保持tcp连接的心跳,这个方式是为了每次心跳都传参
136 | // 也可以使用一下的方式,使用ice自带的功能保持tcp的连接心跳,无法每次心跳传参
137 | // holdHeartbeat(switchPushPrx.ice_getConnection());
138 | } catch (Exception e) {
139 | e.printStackTrace();
140 | }
141 |
142 | communicator().waitForShutdown();
143 |
144 | return 0;
145 | }
146 |
147 | public void destroy() {
148 | if (null != communicator) {
149 | communicator.destroy();
150 | }
151 | }
152 |
153 | /**
154 | * ice自带保持心跳
155 | *
156 | * @author jerome
157 | * @param con
158 | */
159 | @SuppressWarnings("unused")
160 | private void holdHeartbeat(Ice.Connection con) {
161 |
162 | con.setCallback(new Ice.ConnectionCallback() {
163 | @Override
164 | public void heartbeat(Ice.Connection c) {
165 | System.out.println("sn:" + sn + " client heartbeat....");
166 | }
167 |
168 | @Override
169 | public void closed(Ice.Connection c) {
170 | System.out.println("sn:" + sn + " " + "closed....");
171 | }
172 | });
173 |
174 | // 每30/2 s向对方做心跳
175 | // 客户端向服务端做心跳 服务端打印服务端的con.setCallback(new Ice.ConnectionCallback()
176 | con.setACM(new Ice.IntOptional(10), new Ice.Optional(Ice.ACMClose.CloseOff),
177 | new Ice.Optional(Ice.ACMHeartbeat.HeartbeatAlways));
178 |
179 | }
180 |
181 | }
182 |
--------------------------------------------------------------------------------
/src/test/resources/SwitchClient.conf:
--------------------------------------------------------------------------------
1 | #
2 | # The server creates one single object adapter with the name
3 | # "Hello". The following line sets the endpoints for this
4 | # adapter.
5 | #
6 | LzPushClient.Endpoints=default
7 |
8 | #
9 | # Warn about connection exceptions
10 | #
11 | Ice.Warn.Connections=1
12 |
13 | #
14 | # Server-side ACM is disabled by default. For this demo, we want it
15 | # enabled and set to a short timeout of 10 seconds. By enabling
16 | # network tracing below, you can see ACM automatically close idle
17 | # connections.
18 | #
19 | #Ice.ACM.Server=10
20 |
21 | #Ice.MessageSizeMax=4096
22 |
23 | #
24 | # Network Tracing
25 | #
26 | # 0 = no network tracing
27 | # 1 = trace connection establishment and closure
28 | # 2 = like 1, but more detailed
29 | # 3 = like 2, but also trace data transfer
30 | #
31 | Ice.Trace.Network=1
32 |
33 |
34 | #Ice.Override.ConnectTimeout=5000
35 | #Ice.Override.Timeout=50000
36 |
37 | #Ice.StdOut=../log/lzpush_ice.out
38 | #Ice.StdErr=../log/lzpush_ice.err
39 |
40 | #
41 | # Protocol Tracing
42 | #
43 | # 0 = no protocol tracing
44 | # 1 = trace protocol messages
45 | #
46 | #Ice.Trace.Protocol=1
47 |
48 | # 设置连接不自动关闭
49 | # Ice.ACM.Close=0
--------------------------------------------------------------------------------