SSM配置Socket多线程编程(RFID签到实例)
1、SocketServiceLoader.java
package cn.xydata.pharmacy.api.app.test; import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener; /**
* 将socket service随tomcat启动
*
* @author huajian
*/
public class SocketServiceLoader implements ServletContextListener {
// socket server 线程
private SocketThread socketThread; @Override
public void contextDestroyed(ServletContextEvent arg0) {
if (null != socketThread && !socketThread.isInterrupted()) {
socketThread.closeSocketServer();
socketThread.interrupt();
}
} @Override
public void contextInitialized(ServletContextEvent arg0) {
// TODO Auto-generated method stub
if (null == socketThread) {
// 新建线程类
socketThread = new SocketThread(null);
// 启动线程
socketThread.start();
}
}
}
2、SocketThread.java
package cn.xydata.pharmacy.api.app.test; import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException; import javax.servlet.ServletContext; /**
* socket 线程类
*
* @author huajian
*/
public class SocketThread extends Thread {
private ServerSocket serverSocket = null; public SocketThread(ServerSocket serverScoket) {
try {
if (null == serverSocket) {
//InetAddress address=InetAddress.getByName("192.168.0.4");
//System.out.println("服务器ip:"+address);
//this.serverSocket = new ServerSocket(6002,5,address);
this.serverSocket = new ServerSocket(6002);
System.out.println("socket start");
}
} catch (Exception e) {
System.out.println("SocketThread创建socket服务出错");
e.printStackTrace();
} } public void run() {
while (!this.isInterrupted()) {
try {
Socket socket = serverSocket.accept(); if (null != socket && !socket.isClosed()) {
// 处理接受的数据
new SocketOperate(socket).start();
}
socket.setSoTimeout(0); } catch (Exception e) {
e.printStackTrace();
}
}
} public void closeSocketServer() {
try {
if (null != serverSocket && !serverSocket.isClosed()) {
serverSocket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public static void main(String[] args) throws UnknownHostException {
InetAddress address=InetAddress.getByName("180");
System.out.println(address.getHostName());//需要访问DNS服务器才能得到域名
InetAddress address1=InetAddress.getByName("1.2.3.4");//IP地址不存在
System.out.println(address1.getHostName());//直接返回IP地址
}
}
3、SocketOperate.java
package cn.xydata.pharmacy.api.app.test; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.TreeMap; import javax.servlet.ServletContext; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import cn.xydata.pharmacy.api.app.wx.Test1;
import cn.xydata.pharmacy.api.app.wx.WxAPI;
import cn.xydata.pharmacy.dao.meetings.MeetingDao;
import cn.xydata.pharmacy.dto.meetings.MeetingEquipmentDto;
import cn.xydata.pharmacy.dto.meetings.MeetingInfoDto;
import cn.xydata.pharmacy.dto.meetings.MeetingParticipantDto;
import cn.xydata.pharmacy.dto.meetings.ParticipantInfoDto;
import cn.xydata.pharmacy.dto.wechat.AccessTokenDto;
import cn.xydata.pharmacy.service.WechatMsgService;
import cn.xydata.pharmacy.util.CommonUtil;
import cn.xydata.pharmacy.util.DateUtil;
import cn.xydata.pharmacy.util.WsPool;
import cn.xydata.pharmacy.wechat.AccessToken;
import cn.xydata.pharmacy.wechat.HttpReqUtil;
import cn.xydata.pharmacy.wechat.JsonUtil;
import cn.xydata.pharmacy.wechat.SystemConstant;
import cn.xydata.pharmacy.wechat.TemplateMsgResult;
import cn.xydata.pharmacy.wechat.WechatConfig;
import cn.xydata.pharmacy.wechat.WechatTemplateMsg;
import cn.xydata.pharmacy.wechat.enterprise.EwConfig;
import cn.xydata.pharmacy.wechat.enterprise.MessageModel; /**
* 多线程处理socket接收的数据
*
* @author huajian
*
*/
@Component
public class SocketOperate extends Thread { @Autowired
private WechatMsgService wechatMsgService; @Autowired
private MeetingDao meetingDao; private Socket socket; public SocketOperate() {
super();
}
public static SocketOperate socketOperate; public void init() throws Exception {
socketOperate = this;
} public SocketOperate(Socket socket) {
this.socket = socket;
} @SuppressWarnings("unused")
public void run() {
try { InputStream in = socket.getInputStream(); PrintWriter out = new PrintWriter(socket.getOutputStream()); // BufferedReader wt = new BufferedReader(new
// InputStreamReader(System.in));
byte b[]=new byte[10];
String string = "";
// while(in.read(b) != -1) {
//in.read(readBytesFromInputStream(in, 10));
while(in.read(b) != -1) {
System.out.println("原始数据changdu:"+in.read(b));
string = Test1.bytesToHexFun2(b);
System.out.println("客户端发来:" + string.toString());
//List<String> listData = getSocketDatas(string);
// for(String s : listData){
//string = string.substring(string.indexOf("00008"), string.indexOf("00008")+8);
//获取access_token
if("09".equals(string.substring(0, 2)) && string.indexOf("00008") != -1){
String czsbNo = "";
for(MeetingEquipmentDto me : queryEquipment("czsb")){ //车载识别推送
czsbNo += me.geteNo() + "|";
}
if(queryEquipment("hyqd").get(0).geteNo().equals(string.substring(2, 4))){ //签到消息推送
signTemplatePush(string);
}else if(queryEquipment("cjldts").get(0).geteNo().equals(string.substring(2, 4))){ //车间亮点推送
normalPush(string);
}else if(czsbNo.indexOf(string.substring(2, 4)) != -1){ //车载识别
pushCarSign(string);
}
}
//out.flush();
//out.close(); }
//socket.close();
//System.out.println("socket stop....."); } catch (IOException ex) { } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally { }
} public static List<MeetingEquipmentDto> queryEquipment(String useNo){
MeetingEquipmentDto me = new MeetingEquipmentDto();
me.setUseNo(useNo);
return socketOperate.meetingDao.queryEquipment(me);
} //推送会议签到消息
public static void signTemplatePush(String string) throws Exception{
string = string.substring(string.indexOf("00008"), string.indexOf("00008")+8);
//根据最小时间差获取会议信息
MeetingInfoDto meeting = SocketOperate.getCloseTime();
//根据openId获取RFID卡号获取用户信息
ParticipantInfoDto pid = new ParticipantInfoDto();
pid.setRfidNo(string);
List<ParticipantInfoDto> participants = socketOperate.meetingDao.queryAllParticipants(pid);
if(participants.size() > 0){
pid = participants.get(0);
MeetingParticipantDto mp = new MeetingParticipantDto();
mp.setMpId(pid.getMpId());
mp.setMiId(meeting.getMiId());
mp.setIsDeleted(10);
List<MeetingParticipantDto> mps = socketOperate.meetingDao.queryMeetingParticipants(mp);
if(mps.size() > 0){
mp = mps.get(0);
//只给未签到的用户推送消息
int diffMinuter = DateUtil.difftimeByMinutes(DateUtil.getDateFormatByMm(new Date()), meeting.getStartTime());
if(mp.getIsSign() == 10 ){
mp.setIsSign(11);
mp.setSignTime(DateUtil.getDateFormatBySS(new Date()));
mp.setRealName(pid.getRealName());
ParticipantInfoDto bean = new ParticipantInfoDto();
bean.setMpId(mp.getMpId());
ParticipantInfoDto p = socketOperate.meetingDao.queryAllParticipants(bean).get(0);
socketOperate.meetingDao.updateMp(mp);
WsPool.sendMessageToAll(p.getRealName()+","+p.getPosition()+","+mp.getSeatNo()); MessageModel model = new MessageModel();
model.setContent(queryEquipment("hyqd").get(0).getPushContent());
model.setTousers(mp.getWeChat());
WxAPI w = new WxAPI();
w.sendText(model);
}
}
}
} //车间亮点推送
public static void normalPush(String string) throws Exception{
string = string.substring(string.indexOf("00008"), string.indexOf("00008")+8);
//根据最小时间差获取会议信息
MeetingInfoDto meeting = SocketOperate.getCloseTime();
//根据openId获取RFID卡号获取用户信息
ParticipantInfoDto pid = new ParticipantInfoDto();
pid.setRfidNo(string);
List<ParticipantInfoDto> participants = socketOperate.meetingDao.queryAllParticipants(pid);
if(participants.size() > 0){
pid = participants.get(0);
MeetingParticipantDto mp = new MeetingParticipantDto();
mp.setMpId(pid.getMpId());
mp.setMiId(meeting.getMiId());
mp.setIsDeleted(10);
List<MeetingParticipantDto> mps = socketOperate.meetingDao.queryMeetingParticipants(mp);
if(mps.size() > 0){
mp = mps.get(0);
//只给未推送的用户推送消息
int diffMinuter = DateUtil.difftimeByMinutes(DateUtil.getDateFormatByMm(new Date()), meeting.getStartTime());
if(mp.getIsPush() == 10 ){
mp.setIsPush(11);
ParticipantInfoDto bean = new ParticipantInfoDto();
bean.setMpId(mp.getMpId());
ParticipantInfoDto p = socketOperate.meetingDao.queryAllParticipants(bean).get(0);
socketOperate.meetingDao.updateMp(mp);
// WsPool.sendMessageToAll(p.getRealName()+","+p.getPosition()+","+mp.getSeatNo()); MessageModel model = new MessageModel();
model.setContent(queryEquipment("cjldts").get(0).getPushContent());
model.setTousers(mp.getWeChat());
WxAPI w = new WxAPI();
w.sendText(model);
}
}
}
} //推送车辆签到消息
public static void pushCarSign(String string) throws Exception{
string = string.substring(string.indexOf("00008"), string.indexOf("00008")+8);
//根据最小时间差获取会议信息
MeetingInfoDto meeting = SocketOperate.getCloseTime();
//根据openId获取RFID卡号获取用户信息
ParticipantInfoDto pid = new ParticipantInfoDto();
pid.setRfidNo(string);
List<ParticipantInfoDto> participants = socketOperate.meetingDao.queryAllParticipants(pid);
if(participants.size() > 0){
pid = participants.get(0);
MeetingParticipantDto mp = new MeetingParticipantDto();
mp.setMpId(pid.getMpId());
mp.setMiId(meeting.getMiId());
mp.setIsDeleted(10);
List<MeetingParticipantDto> mps = socketOperate.meetingDao.queryMeetingParticipants(mp);
if(mps.size() > 0){
mp = mps.get(0);
//只给未签到的用户推送消息
//int diffMinuter = DateUtil.difftimeByMinutes(DateUtil.getDateFormatByMm(new Date()), meeting.getStartTime());
if(!(string.substring(2, 4)).equals(mp.getCarNo())){ //上错车
//个人推送
MessageModel model = new MessageModel();
model.setContent("车辆签到失败,您上错车啦,请联系引导员");
model.setTousers(mp.getWeChat());
WxAPI w = new WxAPI();
w.sendText(model); //引导员推送(暂不需要)
// MeetingParticipantDto ydy = new MeetingParticipantDto();
// ydy.setCarNo(string);
// ydy.setIsCarLeader(10);
// List<MeetingParticipantDto> ydys = socketOperate.meetingDao.queryMeetingParticipants(ydy);
// ydy = ydys.get(0);
// MessageModel model2 = new MessageModel();
// model2.setContent("有乘客上错车,该乘客姓名为:"+mp.getRealName()+",手机号为:"+mp.getTelephone()+",请联系该乘客换乘正确的车辆!");
// model2.setTousers(ydy.getWeChat());
// WxAPI w2 = new WxAPI();
// w2.sendText(model2);
}else{ //未上错车
if(mp.getIsCarSign() == 10){
mp.setIsCarSign(11);
mp.setCarSignTime(DateUtil.getDateFormatBySS(new Date()));
mp.setRealName(pid.getRealName());
ParticipantInfoDto bean = new ParticipantInfoDto();
bean.setMpId(mp.getMpId());
ParticipantInfoDto p = socketOperate.meetingDao.queryAllParticipants(bean).get(0);
socketOperate.meetingDao.updateMp(mp);
//WsPool.sendMessageToAll(p.getRealName()+","+p.getPosition()+","+mp.getSeatNo()); MessageModel model = new MessageModel();
model.setContent("车辆签到成功");
model.setTousers(mp.getWeChat());
WxAPI w = new WxAPI();
w.sendText(model);
}
} }
}
} //推送通知消息
public static void noticeTemplatePush(String string) throws Exception{
string = string.substring(string.indexOf("00008"), string.indexOf("00008")+8);
String access_Token = obtainAccessToken();
//根据最小时间差获取会议信息
MeetingInfoDto meeting = SocketOperate.getCloseTime();
//根据openId获取RFID卡号获取用户信息
ParticipantInfoDto pid = new ParticipantInfoDto();
pid.setRfidNo(string);
List<ParticipantInfoDto> participants = socketOperate.meetingDao.queryAllParticipants(pid);
List<MeetingParticipantDto> mps = new ArrayList<MeetingParticipantDto>();
MeetingParticipantDto mp = new MeetingParticipantDto();
if(participants.size() > 0){
pid = participants.get(0);
mp.setMpId(pid.getMpId());
mp.setMiId(meeting.getMiId());
mp.setIsDeleted(10);
mp.setIsLead(10);
mps = socketOperate.meetingDao.queryMeetingParticipants(mp);
if(mps.size() > 0){
mp = mps.get(0); //领队个人参会信息
int diffMinuter = DateUtil.difftimeByMinutes(DateUtil.getDateFormatByMm(new Date()), meeting.getStartTime()); if("".equals(mp.getRemark()) || mp.getRemark() == null ){
mp.setRemark("11");
socketOperate.meetingDao.updateMp(mp);
//根据领队个人参会信息查询除该领队外的所有小组成员参会信息
List<MeetingParticipantDto> allMs = new ArrayList<MeetingParticipantDto>();
allMs = socketOperate.meetingDao.queryMeetingParticipantsExpectSelf(mp);
for(MeetingParticipantDto m : allMs){
if(!"".equals(m.getWeChat())){
//拼接推送信息
TreeMap<String, TreeMap<String, String>> params = new TreeMap<String, TreeMap<String, String>>();
// 根据具体模板参数组装
params.put("first", WechatTemplateMsg.item("欢迎来到卷包车间F5机台,请点击查看详细内容", "#000000"));
params.put("keyword1", WechatTemplateMsg.item("ZB48包装机组", "#000000"));
params.put("keyword2", WechatTemplateMsg.item("会务组", "#000000"));
params.put("remark", WechatTemplateMsg.item("", "#000000"));
WechatTemplateMsg wechatTemplateMsg = new WechatTemplateMsg();
//模板ID (签到成功通知)
wechatTemplateMsg.setTemplate_id(WechatConfig.TEMPLATE_FWJDTX);
wechatTemplateMsg.setTouser(m.getWeChat());
//点击跳转url(客户端首页)
wechatTemplateMsg.setUrl(WechatConfig.TEMPLATE_FWJDTX_URL);
wechatTemplateMsg.setData(params);
String data = JsonUtil.toJsonString(wechatTemplateMsg);
socketOperate.wechatMsgService.sendTemplate(null,access_Token, data);
}
}
}
}
}
} private static List<String> getSocketDatas(String datas){
List<String> list = new ArrayList<String>();
String arr[] = datas.split("00008");
for(int i=1;i<arr.length;i++){
list.add("00008"+arr[i].substring(0, 3));
}
list = removeDuplicate(list);
return list;
}
private static List<String> removeDuplicate(List<String> list) {
LinkedHashSet<String> set = new LinkedHashSet<String>(list.size());
set.addAll(list);
list.clear();
list.addAll(set);
return list;
} //获取access_token 公用方法
public static String obtainAccessToken() throws Exception{
AccessTokenDto accessToken = new AccessTokenDto();
accessToken.setAgentId(EwConfig.AGENT_ID);
accessToken = socketOperate.meetingDao.queryAccessToken(accessToken);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String access_Token = "";
//过期
// System.out.println("当前时间戳:"+new Date().getTime());
// System.out.println("上一次时间戳:"+sdf.parse(accessToken.getCreateTime()).getTime());
// System.out.println("时间差:"+(new Date().getTime() - sdf.parse(accessToken.getCreateTime()).getTime())/1000);
// System.out.println("有效时间:"+Long.valueOf(accessToken.getExpiresIn()));
if(accessToken != null){
if((new Date().getTime() - sdf.parse(accessToken.getCreateTime()).getTime())/1000 > Long.valueOf(accessToken.getExpiresIn())){
accessToken.setAccessToken(getAccessToken().getAccess_token());
accessToken.setExpiresIn(String.valueOf(getAccessToken().getExpires_in()));
accessToken.setCreateTime(DateUtil.getDateFormatBySS(new Date()));
socketOperate.meetingDao.updateAccessToken(accessToken);
}
access_Token = accessToken.getAccessToken();
}else{
AccessTokenDto at = new AccessTokenDto();
at.setAccessToken(getAccessToken().getAccess_token());
at.setExpiresIn(String.valueOf(getAccessToken().getExpires_in()));
at.setCreateTime(DateUtil.getDateFormatBySS(new Date()));
socketOperate.meetingDao.insertAccessToken(at);
access_Token = at.getAccessToken();
}
return access_Token;
} public static AccessToken getAccessToken(){
AccessToken accessToken = null;
Map<String, String> params = new TreeMap<String, String>();
params.put("appid", WechatConfig.APP_ID);
params.put("secret", WechatConfig.APP_SECRET);
String jsonResult = HttpReqUtil.HttpDefaultExecute(SystemConstant.GET_METHOD,
WechatConfig.ACCESS_TOKEN, params, "", null);
accessToken = JsonUtil.fromJsonString(jsonResult, AccessToken.class);
return accessToken;
} public static MeetingInfoDto getCloseTime() throws Exception{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
long diffTime = 0;
long nowTime = new Date().getTime();
MeetingInfoDto model = new MeetingInfoDto();
model.setIsDeleted(10);
List<MeetingInfoDto> meetings = socketOperate.meetingDao.queryMeeting(model);
if(meetings.size() > 0){
diffTime = Math.abs(sdf.parse(meetings.get(0).getStartTime()).getTime() - nowTime);
model = meetings.get(0);
}
for(MeetingInfoDto bean : meetings){
if(diffTime > Math.abs(sdf.parse(bean.getStartTime()).getTime() - nowTime)){
diffTime = Math.abs(sdf.parse(bean.getStartTime()).getTime() - nowTime);
System.out.println(diffTime);
model = bean;
}
}
System.out.println("会议名称:"+model.getTitle());
return model;
} public static void main(String[] args) {
String arg = "0900ee0000800183929277333";
if(arg.indexOf("0008") != -1){
if("00".equals(arg.substring(2, 4))){
System.out.println(arg = arg.substring(arg.indexOf("00008"), arg.indexOf("00008")+8));
System.out.println("执行签到操作");
}else if("01".equals(arg.substring(2, 4))){
System.out.println("执行通知操作");
System.out.println(arg = arg.substring(arg.indexOf("00008"), arg.indexOf("00008")+8));
}
}
}
}
web.xml配置如下:
<!--
<context-param>
<param-name>socketPort</param-name>
<param-value>6000</param-value>
</context-param>
-->
<listener>
<description>Socket服务随web启动而启动</description>
<listener-class>SocketServiceLoader.java路径</listener-class>
</listener>
SSM配置Socket多线程编程(RFID签到实例)的更多相关文章
- C++多线程编程(入门实例)
多线程在编程中有相当重要的地位,我们在实际开发时或者找工作面试时总能遇到多线程的问题,对多线程的理解程度从一个侧面反映了程序员的编程水平. 其实C++语言本身并没有提供多线程机制(当然目前C++ 11 ...
- Socket 多线程编程
前面一片学习了TCP/IP的基础网络编程,并给出了简单的服务端与客户端通信交互的例子.还介绍了UPC的通信例子. 这次学习TCP/IP的多线程编程.因为涉及到TCP/IP一般都是多线程,服务端会一直监 ...
- Linux C Socket TCP编程介绍及实例
转自:https://blog.csdn.net/lell3538/article/details/53335231 { printf("向服务器发送数据:%s\n",sendbu ...
- Java socket 多线程编程 示例
参照网上代码: 1.工程: 2.代码: Client.java package com.my.socket.test; import java.io.BufferedReader; import ja ...
- Win32 API 多线程编程——一个简单实例(含消息参数传递)
Win32 API进行程序设计具有很多优点:应用程序执行代码小,运行效率高,但是他要求程序员编写的代码较多,且需要管理所有系统提供给程序的资源,要求程序员对Windows系统内核有一定的了解,会占用程 ...
- Siege——多线程编程最佳实例
在英语中,“Siege”意为围攻.包围.同时Siege也是一款使用纯C语言编写的开源WEB压测工具,适合在GNU/Linux上运行,并且具有较强的可移植性.之所以说它是多线程编程的最佳实例,主要原因是 ...
- Siege(开源Web压力测试工具)——多线程编程最佳实例
在英语中,"Siege"意为围攻.包围.同时Siege也是一款使用纯C语言编写的开源WEB压测工具,适合在GNU/Linux上运行,并且具有较强的可移植性.之所以说它是多线程编程的 ...
- Delphi Socket通信及多线程编程总结
http://cxhblog.blog.sohu.com/41930676.html 一.Socket通信: Delphi在ScktComp单元中对WinSock进行了封装,该单元提供了TAbstra ...
- C++多线程编程入门之经典实例
多线程在编程中有相当重要的地位,我们在实际开发时或者找工作面试时总能遇到多线程的问题,对多线程的理解程度从一个侧面反映了程序员的编程水平. 其实C++语言本身并没有提供多线程机制,但Windows系统 ...
随机推荐
- iClap助力移动互联网企业实现规范化管理
移动互联网的迅速崛起,智能移动客户端深刻而全面地影响着人类生活与工作习惯.而企业办公已从原始的纸张办公,到固定PC办公,跨入到一个应用范围更广.效率更高的移动办公时代.由静生动,让企业办公更加人性化和 ...
- sgu 100 A+B 解题报告及测试数据
100.A+B time limit per test: 0.25 sec. memory limit per test: 65536 KB 题解:上手题,不解释. 直接上代码: #include & ...
- Centos上安装python3.5以上版本
一.准备工作: yum install zlib-devel yum install openssl-devel 二.安装python3.5 wget https://www.python.org/f ...
- iOS开发之UITableViewController重写
# UITablViewController方法的使用介绍 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // ...
- PreparedStatement和Statement区别详解
技术原理 该 PreparedStatement接口继承Statement,并与之在两方面有所不同: PreparedStatement 实例包含已编译的 SQL 语句.这就是使语句“准备好”.包含于 ...
- 高通camera结构(摄像头基础介绍)
摄像头基础介绍 一.摄像头结构和工作原理. 拍摄景物通过镜头,将生成的光学图像投射到传感器上,然后光学图像被转换成电信号,电信号再经过模数转换变为数字信号,数字信号经过DSP加工处理,再被送到电脑中进 ...
- Python爬虫学习笔记之爬虫基础库
知识预览 beautifulsoup的简单使用 beautifulsoup的遍历文档树 beautifulsoup的搜索文档树 beautifulsoup的css选择器 回到顶部 beautifuls ...
- 一键安装lnmp-mysql(4)
mysql(){cd $pathtar zxvf cmake-2.8.11.2.tar.gzcd cmake-2.8.11.2./configuremakemake installcd ..tar z ...
- kali 2.0下搭建DVWA环境
DVWA (Dam Vulnerable Web Application)DVWA是用PHP+Mysql编写的一套用于常规WEB漏洞教学和检测的WEB脆弱性测试程序.包含了SQL注入.XSS.盲注等常 ...
- 0ctf2017-pages-choices
Pages 题目来自于CCS 2016 <Prefetch Side-Channel Attacks: Bypassing SMAP and Kernel ASLR>,利用intel pr ...