服务端

  1. @Configuration
  2. public class NettySocketConfig {
  3.  
  4. private static final Logger logger = LoggerFactory.getLogger(NettySocketConfig.class);
  5.  
  6. @Bean
  7. public SocketIOServer socketIOServer() {
  8. //创建Socket,并设置监听端口
  9. com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
  10. // 设置主机名,默认是0.0.0.0
  11. config.setHostname("192.168.8.107");
  12. // 设置监听端口
  13. config.setPort(9096);
  14. // 协议升级超时时间(毫秒),默认10000。HTTP握手升级为ws协议超时时间
  15. config.setUpgradeTimeout(10000);
  16. // Ping消息间隔(毫秒),默认25000。客户端向服务器发送一条心跳消息间隔
  17. config.setPingInterval(60000);
  18. // Ping消息超时时间(毫秒),默认60000,这个时间间隔内没有接收到心跳消息就会发送超时事件
  19. config.setPingTimeout(180000);
  20. // 这个版本0.9.0不能处理好namespace和query参数的问题。所以为了做认证必须使用全局默认命名空间
  21. config.setAuthorizationListener(new AuthorizationListener() {
  22. @Override
  23. public boolean isAuthorized(HandshakeData data) {
  24. // 可以使用如下代码获取用户密码信息
  25. //String username = data.getSingleUrlParam("username");
  26. //String password = data.getSingleUrlParam("password");
  27. //logger.info("连接参数:username=" + username + ",password=" + password);
  28. //ManagerInfo managerInfo = managerInfoService.findByUsername(username);
  29. //
  30. //String salt = managerInfo.getSalt();
  31. //String encodedPassword = ShiroKit.md5(password, username + salt);
  32. //// 如果认证不通过会返回一个Socket.EVENT_CONNECT_ERROR事件
  33. //return encodedPassword.equals(managerInfo.getPassword());
  34.  
  35. return true;
  36. }
  37. });
  38.  
  39. final SocketIOServer server = new SocketIOServer(config);
  40. System.out.println("注入SocketIOServer");
  41. return server;
  42. }
  43.  
  44. @Bean
  45. public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
  46. return new SpringAnnotationScanner(socketServer);
  47. }
  48. }
  1. @Component
  2. public class MessageEventHandler {
  3.  
  4. private static final Logger logger = LoggerFactory.getLogger(MessageEventHandler.class);
  5.  
  6. /**
  7. * 服务器socket对象
  8. */
  9. public static SocketIOServer socketIoServer;
  10.  
  11. /**
  12. * 客户端集合
  13. */
  14. static ArrayList<UUID> listClient = new ArrayList<>();
  15.  
  16. /**
  17. * 超时时间
  18. */
  19. static final int limitSeconds = 60;
  20.  
  21. @Autowired
  22. public LoginService loginService;
  23.  
  24. /**
  25. * 初始化消息事件处理器
  26. *
  27. * @param server 服务器socket对象
  28. */
  29. @Autowired
  30. public MessageEventHandler(SocketIOServer server) {
  31. logger.info("初始化SOCKET消息事件处理器");
  32. this.socketIoServer = server;
  33. }
  34.  
  35. /**
  36. * 客户端发起连接时触发
  37. *
  38. * @param client 客户端Socket对象信息
  39. */
  40. @OnConnect
  41. public void onConnect(SocketIOClient client) {
  42. logger.info("客户端{}已连接", client.getSessionId());
  43. listClient.add(client.getSessionId());
  44. }
  45.  
  46. /**
  47. * 客户端断开连接时触发
  48. *
  49. * @param client 客户端Socket对象信息
  50. */
  51. @OnDisconnect
  52. public void onDisconnect(SocketIOClient client) {
  53. logger.info("客户端{}断开连接", client.getSessionId());
  54. if (listClient.contains(client.getSessionId())) {
  55. listClient.remove(client.getSessionId());
  56. }
  57. }
  58.  
  59. /**
  60. * 客户端发送消息时触发
  61. *
  62. * @param client 客户端Socket对象信息
  63. * @param request AckRequest 回调对象
  64. * @param data 消息信息实体
  65. */
  66. @OnEvent(value = SocketConstants.SocketEvent.MESSAGE)
  67. public void onEvent(SocketIOClient client, AckRequest request, MessageInfo data) {
  68. System.out.println("发来消息:" + data.getMsgContent());
  69. socketIoServer.getClient(client.getSessionId()).sendEvent("messageevent", "back data");
  70. }
  71.  
  72. /**
  73. * 效验连接事件并存储客户端信息
  74. *
  75. * @param client 客户端Socket对象信息
  76. * @param data 客户端数据
  77. * @param request AckRequest 回调对象
  78. */
  79. @OnEvent(value = SocketConstants.SocketEvent.HEALTH_CHECK)
  80. public void onEventByHealthCheck(SocketIOClient client, String data, AckRequest request) {
  81. //logger.info("客户端{}效验连接请求", client.getSessionId());
  82. ////解析请求数据
  83. //HealthCheckRequest healthCheckRequest = JSON.parseObject(data, HealthCheckRequest.class);
  84. //if (healthCheckRequest != null) {
  85. // //存储客户端信息
  86. // SocketInstance instance = SocketInstance.getSocketInstance();
  87. // System.out.println(data);
  88. // instance.insertSocketClient(healthCheckRequest.getEnCode(), client);
  89. // logger.info("客户端{}效验连接响应:{}", client.getSessionId(), "OK");
  90. // //响应客户端
  91. // request.sendAckData("OK");
  92. //}
  93. }
  94.  
  95. /**
  96. * 登录事件
  97. *
  98. * @param client 客户端Socket对象信息
  99. * @param data 客户端数据
  100. * @param request AckRequest 回调对象
  101. */
  102. @OnEvent(value = SocketConstants.SocketEvent.LOGIN)
  103. public void onEventByLogin(SocketIOClient client, String data, AckRequest request) {
  104. logger.info("客户端{}登录请求:{}", client.getSessionId(), data);
  105. AppResponseBase appResponseBase = new AppResponseBase(0, "通讯成功");
  106. //业务响应对象
  107. LoginResponse loginResponse = null;
  108. try {
  109. //解析请求数据
  110. LoginRequest loginRequest = JSON.parseObject(data, LoginRequest.class);
  111. if (loginRequest == null) {
  112. throw new AppException(AppResultCode.LoginAnalysis_Fail);
  113. }
  114. //调用登陆接口
  115. loginResponse = loginService.appLogin(loginRequest);
  116. if (loginResponse == null) {
  117. throw new AppException(AppResultCode.LoginCloud_Fail);
  118. }
  119. if (EnumResult.Success.equals(loginResponse.getResultCode())) {
  120. //保存客户端Socket信息
  121. SocketInstance instance = SocketInstance.getSocketInstance();
  122. instance.insertSocketClient(loginRequest.getEnCode(), client);
  123. }
  124. } catch (AppException ex) {
  125. loginResponse = new LoginResponse(ex.getAppResultCode().getCode(), ex.getAppResultCode().getMsg());
  126. } catch (Exception ex) {
  127. loginResponse = new LoginResponse(AppResultCode.Exceptions.getCode(), AppResultCode.Exceptions.getMsg());
  128. ex.printStackTrace();
  129. }
  130. appResponseBase.setRespData(loginResponse);
  131. String result = JSON.toJSONString(appResponseBase);
  132. logger.info("客户端{}登录响应:{}", client.getSessionId(), result);
  133. //响应客户端
  134. request.sendAckData(result);
  135. }
  136.  
  137. /**
  138. * 交易下单事件
  139. * @param callPayRequest 下单请求信息实体
  140. * @return
  141. */
  142. public static String sendByPayEvent(CallPayRequest callPayRequest) {
  143. String result = "";
  144. //获取客户端信息
  145. SocketInstance instance = SocketInstance.getSocketInstance();
  146. SocketIOClient client = instance.getClientSocket(callPayRequest.getEnCode());
  147. if (client != null) {
  148. //请求报文
  149. String requestParam = JSON.toJSONString(callPayRequest);
  150. //请求下单
  151. client.sendEvent(SocketConstants.SocketEvent.PAY, new AckCallback<String>(String.class) {
  152. @Override
  153. public void onSuccess(String s) {
  154. //响应信息
  155. System.out.println("ack from client: " + client.getSessionId() + " data: " + s.toString());
  156. }
  157. }, requestParam);
  158.  
  159. } else {
  160. //客户端已断开连接
  161.  
  162. }
  163. return result;
  164. }
  165. }
  1. @Component
  2. @Order(value = 1)
  3. public class MyCommandLineRunner implements CommandLineRunner {
  4.  
  5. private final SocketIOServer server;
  6.  
  7. @Autowired
  8. public MyCommandLineRunner(SocketIOServer server) {
  9. System.out.println("初始化MyCommandLineRunner");
  10. this.server = server;
  11. }
  12.  
  13. @Override
  14. public void run(String... args) {
  15. try {
  16. server.start();
  17. System.out.println("socket.io启动成功!");
  18. } catch (Exception ex) {
  19. ex.printStackTrace();
  20. }
  21. }
  22. }
  1. public class SocketConstants {
  2.  
  3. /**
  4. * Socket事件类
  5. */
  6. public class SocketEvent {
  7.  
  8. /**
  9. * 效验连接状况
  10. */
  11. public static final String HEALTH_CHECK = "HEALTH_CHECK";
  12.  
  13. /**
  14. * 消息接收事件名称
  15. */
  16. public static final String MESSAGE = "message";
  17.  
  18. /**
  19. * 登录事件名称
  20. */
  21. public static final String LOGIN = "LOGIN";
  22.  
  23. /**
  24. * 获取交易要素事件名称
  25. */
  26. public static final String QUERY_PAY_FIELDS = "QUERY_PAY_FIELDS";
  27.  
  28. /**
  29. * 创建订单事件名称
  30. */
  31. public static final String CREATE_ORDER = "CREATE_ORDER";
  32.  
  33. /**
  34. * 监控订单状态事件名称
  35. */
  36. public static final String CHECK_ORDER_STATUS = "CHECK_ORDER_STATUS";
  37.  
  38. /**
  39. * 获取订单事件名称
  40. */
  41. public static final String QUERY_ORDER = "QUERY_ORDER";
  42.  
  43. /**
  44. * 支付事件名称
  45. */
  46. public static final String PAY = "PAY";
  47. }
  48. }
  1. public class SocketInstance {
  2.  
  3. /**
  4. * 客户端Socket连接对象容器
  5. */
  6. private static Map<String, SocketIOClient> socketClients = null;
  7.  
  8. /**
  9. * 私有构造
  10. */
  11. private SocketInstance() {
  12. //从缓存中获取socketClients
  13. socketClients = new HashMap<>();
  14. }
  15.  
  16. /**
  17. * 定义一个私有的内部类,在第一次用这个嵌套类时,会创建一个实例。而类型为SocketInstanceHolder的类,只有在SocketInstance.getSocketInstance()中调用,
  18. * 由于私有的属性,他人无法使用SocketInstanceHolder,不调用SocketInstance.getSocketInstance()就不会创建实例。
  19. * 优点:达到了lazy loading的效果,即按需创建实例。
  20. * 无法适用于分布式集群部署
  21. */
  22. private static class SocketInstanceHolder {
  23. /**
  24. * 创建全局唯一实例
  25. */
  26. private final static SocketInstance instance = new SocketInstance();
  27. }
  28.  
  29. /**
  30. * 获取全局唯一实例
  31. *
  32. * @return SocketInstance对象
  33. */
  34. public static SocketInstance getSocketInstance() {
  35. return SocketInstanceHolder.instance;
  36. }
  37.  
  38. /**
  39. * 新增客户端连接到容器
  40. *
  41. * @param encode 设备En号
  42. * @param socketIOClient 客户端socket对象
  43. */
  44. public void insertSocketClient(String encode, SocketIOClient socketIOClient) {
  45. SocketIOClient oldSocketIOClient = socketClients.get(encode);
  46. if (oldSocketIOClient != null) {
  47. try {
  48. //关闭客户端连接
  49. oldSocketIOClient.disconnect();
  50. } catch (Exception ex) {
  51. ex.printStackTrace();
  52. }
  53. }
  54. socketClients.put(encode, socketIOClient);
  55. }
  56.  
  57. /**
  58. * 获取客户端Socket对象
  59. *
  60. * @param encode 设备encode
  61. * @return 客户端Socket对象
  62. */
  63. public SocketIOClient getClientSocket(String encode) {
  64. return socketClients.get(encode);
  65. }
  66. }

Android客户端

  1. public class SocketClient {
  2.  
  3. /**
  4. * 最大重连次数
  5. */
  6. private int maxReConnectionCount = 5;
  7.  
  8. /**
  9. * 重连次数
  10. */
  11. private int reConnectionCount = 0;
  12.  
  13. /**
  14. * 等待框对象
  15. */
  16. private static ProgressDialog progressdialog;
  17.  
  18. /**
  19. * 提示框
  20. */
  21. private static AlertDialog.Builder dialogExitBuilder;
  22.  
  23. /**
  24. * Toast提示对象
  25. */
  26. private static Toast toast;
  27.  
  28. /**
  29. * Socket客户端对象信息
  30. */
  31. public static Socket socket;
  32.  
  33. /**
  34. * 主页面对象,每个页面onCreate时必须设置,可在每个页面监控Socket连接状况
  35. */
  36. public static Context nowContext;
  37.  
  38. /**
  39. * Socket连接提示handler(等待框)
  40. */
  41. Handler dialogMessageHandler = new Handler() {
  42. @Override
  43. public void handleMessage(Message msg) {
  44. super.handleMessage(msg);
  45. Bundle bundle = msg.getData();
  46. String message = bundle.getString(MessageUtil.MESSAGE);
  47. setDialogMessage(message);
  48. }
  49. };
  50.  
  51. /**
  52. * Socket连接失败退出提示handler(提示框)
  53. */
  54. Handler dialogExitHandler = new Handler() {
  55. @Override
  56. public void handleMessage(Message msg) {
  57. super.handleMessage(msg);
  58. Bundle bundle = msg.getData();
  59. String message = bundle.getString(MessageUtil.MESSAGE);
  60. dialogExit(message);
  61. }
  62. };
  63.  
  64. /**
  65. * Socket连接提示handler(Toast)
  66. */
  67. Handler toastMessageHandler = new Handler() {
  68. @Override
  69. public void handleMessage(Message msg) {
  70. super.handleMessage(msg);
  71. Bundle bundle = msg.getData();
  72. String message = bundle.getString(MessageUtil.MESSAGE);
  73. showToast(message, Toast.LENGTH_SHORT);
  74. }
  75. };
  76.  
  77. /**
  78. * 等待框
  79. *
  80. * @param message 提示文字
  81. */
  82. private static void setDialogMessage(String message) {
  83. if (progressdialog == null) {
  84. progressdialog = new ProgressDialog(nowContext);
  85. }
  86. progressdialog.setTitle("学通宝收银");
  87. progressdialog.setMessage(message);
  88. progressdialog.setCancelable(false);
  89. progressdialog.show();
  90. }
  91.  
  92. /**
  93. * 退出提示框
  94. *
  95. * @param message 提示文字
  96. */
  97. private void dialogExit(String message) {
  98. //初始化退出builder
  99. if (dialogExitBuilder == null) {
  100. dialogExitBuilder = new AlertDialog.Builder(nowContext);
  101. }
  102. dialogExitBuilder.setMessage(message);
  103. dialogExitBuilder.setTitle("提示");
  104. dialogExitBuilder.setIcon(R.mipmap.warning);
  105. dialogExitBuilder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
  106. public void onClick(DialogInterface dialog, int which) {
  107. dialog.dismiss();
  108. //参数用作状态码;根据惯例,非 0 的状态码表示异常终止。
  109. System.exit(0);
  110. }
  111. });
  112. dialogExitBuilder.create().show();
  113. }
  114.  
  115. /**
  116. * Toast消息提醒
  117. *
  118. * @param text 标题
  119. * @param duration 时长
  120. */
  121. public void showToast(String text, int duration) {
  122. //只创建一次
  123. if (toast == null) {
  124. toast = Toast.makeText(nowContext, text, duration);
  125. } else {
  126. toast.setText(text);
  127. toast.setDuration(duration);
  128. }
  129. toast.show();
  130. }
  131.  
  132. public void startSocket() throws URISyntaxException {
  133. //初始化Socket配置
  134. IO.Options options = new IO.Options();
  135. options.transports = new String[]{"websocket"};
  136. options.reconnectionAttempts = maxReConnectionCount; // 设置一个重连的最大尝试次数,超过这个值后Socket.io会使用所有允许的其他连接方式尝试重连,直到最终失败。
  137. options.reconnectionDelay = 500; //为Socket.io的重连设置一个时间间隔,内部会在多次重连尝试时采用该值的指数值间隔,用来避免性能损耗(500 > 1000 > 2000 > 4000 > 8000)
  138. options.reconnection = true; //当连接终止后,是否允许Socket.io自动进行重连
  139. options.timeout = 9000; //连接超时时间(ms)
  140. options.forceNew = true;
  141. options.query = "appid=cn.xuetongbao.xtbpay";
  142. socket = IO.socket("http://192.168.8.107:9096/", options);
  143. //连接成功
  144. socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
  145. @Override
  146. public void call(Object... args) {
  147. //重连机制
  148. if (reConnectionCount > 0) {
  149. //连接存储客户端信息
  150. DeviceInfoInstance instance = DeviceInfoInstance.getSocketInstance();
  151. HealthCheckRequest healthCheckRequest = new HealthCheckRequest();
  152. healthCheckRequest.setEnCode(instance.getDeviceInfo().getEnCode());
  153. socket.emit(SocketConstants.SocketEvent.HEALTH_CHECK, RequestUtil.createObject(healthCheckRequest), (Ack) args1 -> {
  154. System.out.println("args1:" + args1.toString());
  155. });
  156. }
  157. System.out.println("连接成功...");
  158. toastMessageHandler.sendMessage(MessageUtil.createMessage("服务器连接成功"));
  159. //关闭等待框
  160. if (progressdialog != null) {
  161. progressdialog.dismiss();
  162. }
  163. }
  164. });
  165.  
  166. //连接失败事件
  167. socket.on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
  168. @Override
  169. public void call(Object... args) {
  170. System.out.println("Socket.EVENT_CONNECT_ERROR");
  171. System.out.println("reConnectionCount:" + reConnectionCount);
  172. if (reConnectionCount >= maxReConnectionCount) {
  173. dialogExitHandler.sendMessage(MessageUtil.createMessage("服务器连接失败,请稍后再试"));
  174. } else {
  175. dialogMessageHandler.sendMessage(MessageUtil.createMessage("服务器连接失败,正在重新连接..."));
  176. }
  177. }
  178. });
  179.  
  180. //连接中事件
  181. socket.on(Socket.EVENT_RECONNECTING, new Emitter.Listener() {
  182. @Override
  183. public void call(Object... args) {
  184. reConnectionCount++;
  185. System.out.println("Socket.EVENT_RECONNECTING");
  186. dialogMessageHandler.sendMessage(MessageUtil.createMessage("正在连接服务器..."));
  187. }
  188. });
  189.  
  190. //连接超时事件
  191. socket.on(Socket.EVENT_CONNECT_TIMEOUT, new Emitter.Listener() {
  192. @Override
  193. public void call(Object... args) {
  194. System.out.println("Socket.EVENT_CONNECT_TIMEOUT");
  195. if (nowContext != null) {
  196. dialogMessageHandler.sendMessage(MessageUtil.createMessage("与服务器连接超时,正在重新建立连接..."));
  197. socket.connect();
  198. }
  199. }
  200. });
  201.  
  202. //心跳包
  203. socket.on(Socket.EVENT_PING, new Emitter.Listener() {
  204. @Override
  205. public void call(Object... args) {
  206. System.out.println("Socket.EVENT_PING");
  207. }
  208. });
  209. //心跳包
  210. socket.on(Socket.EVENT_PONG, new Emitter.Listener() {
  211. @Override
  212. public void call(Object... args) {
  213. System.out.println("Socket.EVENT_PONG");
  214. }
  215. });
  216.  
  217. //消息接收事件
  218. socket.on(Socket.EVENT_MESSAGE, new Emitter.Listener() {
  219. @Override
  220. public void call(Object... args) {
  221. System.out.println("-----------接受到消息啦--------" + Arrays.toString(args));
  222. }
  223. });
  224.  
  225. //连接断开事件
  226. socket.on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
  227. @Override
  228. public void call(Object... args) {
  229. reConnectionCount = 0;
  230. System.out.println("客户端断开连接啦。。。");
  231. if (nowContext != null) {
  232. dialogMessageHandler.sendMessage(MessageUtil.createMessage("似乎与服务器断开连接,正在重新建立连接..."));
  233. socket.connect();
  234. }
  235. }
  236. });
  237.  
  238. //交易事件
  239. socket.on(SocketConstants.SocketEvent.PAY, new Emitter.Listener() {
  240. @Override
  241. public void call(Object... args) {
  242. Object data = args[0];
  243. Object ackCallBack = args[1];
  244. System.out.println("接收到服务端交易下单消息" + data);
  245. CallPayRequest callPayRequest = JSON.parseObject(data.toString(), CallPayRequest.class);
  246. if (callPayRequest != null) {
  247.  
  248. }
  249. //data
  250. CallPayResponse callPayResponse = new CallPayResponse();
  251. callPayResponse.setResultCode(AppResultCode.Success.getCode());
  252. callPayResponse.setResultMsg(AppResultCode.Success.getMsg());
  253.  
  254. //响应服务端
  255. ((Ack) ackCallBack).call(JSON.toJSONString(callPayResponse));
  256. }
  257. });
  258. System.out.println("准备连接服务器...");
  259. socket.connect();
  260. }
  261. }

 注:仅供学习参考

【Spring Boot】集成Netty Socket.IO通讯框架的更多相关文章

  1. spring boot集成MyBatis 通用Mapper 使用总结

    spring boot集成MyBatis 通用Mapper 使用总结 2019年 参考资料: Spring boot集成 MyBatis 通用Mapper SpringBoot框架之通用mapper插 ...

  2. Spring Boot集成Jasypt安全框架

    Jasypt安全框架提供了Spring的集成,主要是实现 PlaceholderConfigurerSupport类或者其子类. 在Sring 3.1之后,则推荐使用PropertySourcesPl ...

  3. Spring Boot集成Reactor事件处理框架的简单示例

    1. Reactor简介 Reactor 是 Spring 社区发布的基于事件驱动的异步框架,不仅解耦了程序之间的强调用关系,而且有效提升了系统的多线程并发处理能力. 2. Spring Boot集成 ...

  4. Spring Boot 2.X(六):Spring Boot 集成Redis

    Redis 简介 什么是 Redis Redis 是目前使用的非常广泛的免费开源内存数据库,是一个高性能的 key-value 数据库. Redis 与其他 key-value 缓存(如 Memcac ...

  5. Spring boot集成swagger2

    一.Swagger2是什么? Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件. Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格 ...

  6. Spring Boot 集成 Swagger,生成接口文档就这么简单!

    之前的文章介绍了<推荐一款接口 API 设计神器!>,今天栈长给大家介绍下如何与优秀的 Spring Boot 框架进行集成,简直不能太简单. 你所需具备的基础 告诉你,Spring Bo ...

  7. spring boot 集成 zookeeper 搭建微服务架构

    PRC原理 RPC 远程过程调用(Remote Procedure Call) 一般用来实现部署在不同机器上的系统之间的方法调用,使得程序能够像访问本地系统资源一样,通过网络传输去访问远程系统资源,R ...

  8. Quartz与Spring Boot集成使用

    上次自己搭建Quartz已经是几年前的事了,这次项目中需要定时任务,需要支持集群部署,想到比较轻量级的定时任务框架就是Quartz,于是来一波. 版本说明 通过搜索引擎很容易找到其官网,来到Docum ...

  9. Spring Boot集成MyBatis开发Web项目

    1.Maven构建Spring Boot 创建Maven Web工程,引入spring-boot-starter-parent依赖 <project xmlns="http://mav ...

随机推荐

  1. CF1137E. Train Car Selection(可删堆)

    题面 三个操作 1.在当前数列最左端加入\(k\)个初始为\(0\)的数 2.在当前数列最右端加入\(k\)个初始为\(0\)的数 3.将当前数列从左到右第\(i\)个数加上\(b+(i-1)k(b& ...

  2. SqlServer批量插入(SqlBulkCopy、表值参数)

    之前做项目需要用到数据库的批量插入,于是就研究了一下,现在做个总结. 创建了一个用来测试的Student表: CREATE TABLE [dbo].[Student]( [ID] [int] PRIM ...

  3. [POI2007]MEG-Megalopolis 树的dfs序+树状数组维护差分 BZOJ1103

    题目描述 Byteotia has been eventually touched by globalisation, and so has Byteasar the Postman, who onc ...

  4. JS中Math函数的常用方法

    Math 是数学函数,但又属于对象数据类型 typeof Math => ‘object’ console.dir(Math) 查看Math的所有函数方法. 1,Math.abs() 获取绝对值 ...

  5. mysql id_logfile 日志

    ib_logfile 文件原理 ib_logfile0 是innodb中事务日志,记录系统的回滚,重做日志,记录的是文件的物理更改,存放位置my.ini 中的 datadir="D:\php ...

  6. Week 5: Object Oriented Programming 9. Classes and Inheritance Exercise: int set

    class intSet(object): """An intSet is a set of integers The value is represented by a ...

  7. 最小生成树----prim算法的堆优化

    题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz 输入输出格式 输入格式: 第一行包含两个整数N.M,表示该图共有N个结点和M条无向边.(N<=5000,M<= ...

  8. HDU 5938 Kingdom of Obsession(数论 + 二分图匹配)

    题意: 给定S,N,把S+1,S+2,...S+N这N个数填到1,2,...,N里,要求X只能填到X的因子的位置.(即X%Y=0,那么X才能放在Y位置) 问是否能够放满. 分析:经过小队的分析得出的结 ...

  9. (转)数位dp

    原博客 https://blog.csdn.net/wust_zzwh/article/details/52100392 建议原博客看到hdu 不要62,然后看我分割线后两道题,然后再回来看原博.-- ...

  10. C++ GUI Qt4编程(01)-1.1Hello Qt

    1. 根据C++ GUI Qt4编程(第二版)整理2. 系统:centos7:  Qt版本:5.5.13. 程序:hello.cpp #include <QApplication> #in ...