├── .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 --------------------------------------------------------------------------------