前言

  • 在实际中我们有时候会产生这样一个需求:进制某一台设备接入无线网络,如果已经接入 则让其强制下线。并且,下线后不能再次接入,除非放行该设备
  • 这里产生了两个需求:1.将终端设备踢下线。 2.不能让终端设备再次上线。下面我们来分析这两个需求实现的原理

无线设备认证和交互流程

这里我就直接贴网上的链接了https://blog.csdn.net/hmxz2nn/article/details/79937344
总的来说分为三步:扫描,认证和关联。认证和关联都伴随着sta发送请求和ap回复请求。这里我们采用的就是在认证或者关联代码处动手脚

怎么才能让STA下线

  • 关于这个问题,我们需要了解一下无线的帧类型。这方面相关的资料网上也是有的,这里我也不再详细介绍,只列出几个重要的知识点。

请注意这里的管理帧 ,管理帧包括STA的加入和退出。本质上来说就是解除关联的帧。(上面提到了认证和关联。这里是相反的,即解除关联)

由此我们可以得出:我们需要发送给指定的STA解除关联的数据报文(即给指定mac的设备发送解除关联的数据报文)

  • 由此这里又产生了一个问题:怎么构造和发送该管理帧。其实在现在的网卡驱动程序或者嵌入式网卡模块中,都已经集成了该命令(需要注意的是每个厂商的控制指令集不一样,但是基本都是基于知名网络控制工具来实现的-wirelessTools和iw)。嵌入式可能使用的是AT指令

iw和iwpriv的区别

  • iw 是一种新的基于 nl80211 的用于无线设备的CLI配置实用程序。应用层和驱动层采用的是netlink通信方式。而iwpriv是基于老的ioctl的方式进行通信。ioctl所支持的数量是有限制的。

怎么查看iwpriv支持的命令列表

  • 厂商如果是用iwpriv作为无线的控制命令,那么内核一定会存在iwpriv支持的一系列命令列表。如果我们在应用层调用iwpriv命令,但是实际没有得到我们想要的效果,那么唯一存在的可能性就是厂商在内核没有实现该命令。
  • 在linux内核中struct iw_priv_args结构体是作为iwpriv内核命令列表所对应的结构体。
struct   iw_priv_args
{__u32      cmd;        /* Number of the ioctl to issue */__u16     set_args;   /* Type and number of args */__u16      get_args;   /* Type and number of args */char       name[IFNAMSIZ]; /* Name of the extension */
};

在厂商所对应的驱动文件中一定会定义该结构体,这里以rtl8197f芯片为例。

struct iw_priv_args privtab[] = {#if defined(CONFIG_RTL_P2P_SUPPORT) && defined(RTK_NL80211) /*cfg p2p cfg p2p*/{ RTL8192CD_IOCTL_FROM_ANDROID, IW_PRIV_TYPE_CHAR | 512, IW_PRIV_TYPE_BYTE | 512 , "hostapd_ioctlcmd" },
#endif{ RTL8192CD_IOCTL_SET_MIB, IW_PRIV_TYPE_CHAR | 450, 0, "set_mib" },{ RTL8192CD_IOCTL_GET_MIB, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "get_mib" },
#ifdef _IOCTL_DEBUG_CMD_{ RTL8192CD_IOCTL_WRITE_REG, IW_PRIV_TYPE_CHAR | 128, 0, "write_reg" },{ RTL8192CD_IOCTL_READ_REG, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | 128, "read_reg" },{ RTL8192CD_IOCTL_WRITE_MEM, IW_PRIV_TYPE_CHAR | 128, 0, "write_mem" },{ RTL8192CD_IOCTL_READ_MEM, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | 128, "read_mem" },{ RTL8192CD_IOCTL_WRITE_BB_REG, IW_PRIV_TYPE_CHAR | 128, 0, "write_bb" },{ RTL8192CD_IOCTL_READ_BB_REG, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | 128, "read_bb" },{ RTL8192CD_IOCTL_WRITE_RF_REG, IW_PRIV_TYPE_CHAR | 128, 0, "write_rf" },{ RTL8192CD_IOCTL_READ_RF_REG, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | 128, "read_rf" },
#endif{ RTL8192CD_IOCTL_DUMP_MIB, IW_PRIV_TYPE_CHAR | 40, 0, "dump_mib" },{ RTL8192CD_IOCTL_DEL_STA, IW_PRIV_TYPE_CHAR | 128, 0, "del_sta" },{ RTL8192CD_IOCTL_WRITE_EEPROM, IW_PRIV_TYPE_CHAR | 128, 0, "write_eeprom" },{ RTL8192CD_IOCTL_READ_EEPROM, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | 128, "read_eeprom" },

注意:一定要在对应厂商所使用的芯片驱动中查找

  • 在应用层我们可以列出iwpriv所支持的命令列表。

    iwpriv中有一条del_sta 这里感觉就是我们想找的了。接着我们查看内核中iwpriv的命令列表。在该结构体的定义中我们可以看到这样一句
{ RTL8192CD_IOCTL_DEL_STA, IW_PRIV_TYPE_CHAR | 128, 0, "del_sta" },

我们接着跟踪,会找到RTL8192CD_IOCTL_DEL_STA的分支处理代码

 case RTL8192CD_IOCTL_DEL_STA:if ((wrq->u.data.length > sizeof_tmpbuf) ||ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length))break;// del_sta branch 4, IOCTL "del_sta"priv->del_sta_info.branch_code = 4;DRV_RT_TRACE(priv, DRV_DBG_CONN_INFO, DRV_DBG_SERIOUS, " IOCTL_DEL_STA del_sta %02X%02X%02X%02X%02X%02X\n",tmpbuf[0], tmpbuf[1], tmpbuf[2], tmpbuf[3], tmpbuf[4], tmpbuf[5]);ret = del_sta(priv, tmpbuf);break;

在这里我们可以看到,ioctl_copy_from_user从应用层拷贝,然后调用了del_sta。这里我们通过对代码的分析和猜想从应用层传递的拷贝到tmpbuf中的肯定是sta的mac地址(注:在网络通信中,操作sta只认mac。mac地址是唯一的。mac地址只是在局域网中有用
所以我们只要在应用层调用iwpriv wlan0/wlan1 del_sta XXXXXXXXXXXX即可踢出设备下线(本质上发送的是解除关联的管理帧)

iw命令在内核中的实现

这里贴一个链接地址,然后结合代码就可以找到https://zhuanlan.zhihu.com/p/141630753

  • 我们来看看rtl中有哪些实现,不同厂商所支持的iw命令集有可能不一样(最主要的就是实现cfg80211_ops结构体)
struct cfg80211_ops realtek_cfg80211_ops = {.add_virtual_intf = realtek_cfg80211_add_iface,.del_virtual_intf = realtek_cfg80211_del_iface,.change_virtual_intf = realtek_cfg80211_change_iface,.add_key = realtek_cfg80211_add_key,.del_key = realtek_cfg80211_del_key,.get_key = realtek_cfg80211_get_key,.set_default_key = realtek_cfg80211_set_default_key,.set_default_mgmt_key = realtek_cfg80211_set_default_mgmt_key,//.add_beacon = realtek_cfg80211_add_beacon,//.set_beacon = realtek_cfg80211_set_beacon,//.del_beacon = realtek_cfg80211_del_beacon,.add_station = realtek_cfg80211_add_station,.del_station = realtek_cfg80211_del_station,.change_station = realtek_cfg80211_change_station,.get_station = realtek_cfg80211_get_station,.dump_station = realtek_cfg80211_dump_station,
#if 0//def CONFIG_MAC80211_MESH.add_mpath = realtek_cfg80211_add_mpath,.del_mpath = realtek_cfg80211_del_mpath,.change_mpath = realtek_cfg80211_change_mpath,.get_mpath = realtek_cfg80211_get_mpath,.dump_mpath = realtek_cfg80211_dump_mpath,.set_mesh_params = realtek_cfg80211_set_mesh_params,.get_mesh_params = realtek_cfg80211_get_mesh_params,
#endif.change_bss = realtek_cfg80211_change_bss,//.set_txq_params = realtek_cfg80211_set_txq_params,//.set_channel = realtek_cfg80211_set_channel,.suspend = realtek_cfg80211_suspend,.resume = realtek_cfg80211_resume,.scan = realtek_cfg80211_scan,
#if 0.auth = realtek_cfg80211_auth,.assoc = realtek_cfg80211_assoc,.deauth = realtek_cfg80211_deauth,.disassoc = realtek_cfg80211_disassoc,
#endif.join_ibss = realtek_cfg80211_join_ibss,.leave_ibss = realtek_cfg80211_leave_ibss,.set_wiphy_params = realtek_cfg80211_set_wiphy_params,.set_ap_chanwidth = realtek_cfg80211_set_ap_chanwidth,.set_monitor_channel = realtek_cfg80211_set_monitor_channel,.set_tx_power = realtek_cfg80211_set_tx_power,.get_tx_power = realtek_cfg80211_get_tx_power,.set_power_mgmt = realtek_cfg80211_set_power_mgmt,.set_wds_peer = realtek_cfg80211_set_wds_peer,.rfkill_poll = realtek_cfg80211_rfkill_poll,//CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd).set_bitrate_mask = realtek_cfg80211_set_bitrate_mask,.connect = realtek_cfg80211_connect,.disconnect = realtek_cfg80211_disconnect,#if defined(P2P_SUPPORT).remain_on_channel = realtek_remain_on_channel,.cancel_remain_on_channel = realtek_cancel_remain_on_channel,#endif.mgmt_tx = realtek_mgmt_tx,.mgmt_frame_register = realtek_mgmt_frame_register,.channel_switch = realtek_cfg80211_channel_switch,.dump_survey = realtek_dump_survey,//survey_dump.start_ap = realtek_start_ap,.change_beacon = realtek_change_beacon,.stop_ap = realtek_stop_ap,
#if 0.sched_scan_start = realtek_cfg80211_sscan_start,.sched_scan_stop = realtek_cfg80211_sscan_stop,.set_bitrate_mask = realtek_cfg80211_set_bitrate,.set_cqm_txe_config = realtek_cfg80211_set_txe_config,
#endif.set_mac_acl = realtek_set_mac_acl,
#if defined(DFS).start_radar_detection = realtek_start_radar_detection
#endif
};

使用iw dev [Interface] station del [MAC address]将STA踢下线

STA踢出下线后,怎样禁止该STA再次连接

说明: 按照上述的方式是可以将对应mac的sta踢出下线的。但是,这里达不到我们的需求。原因分析如下:当我们调用iwpriv或者iw命令将对应的mac终端设备踢出下线后,终端设备会再次选择加入一个无线局域网。(有可能选择的是和以前不同的局域网,也有可能仍然连接到原来的局域网,因为ap没有修改无线的配置。终端设备仍然能够扫描,认证和关联成功)

解决问题方案分析

为了解决我们上述所提出的问题,我们可以在两个地方做文章。这两个地方分别是认证和关联处,只要我们不让对应的终端设备任何和关联成功,即可不让终端连接成功(也可以在驱动收包处来做包的匹配,如果是该mac的数据报文则丢弃,但是这里我不建议这样做,在驱动做会降低数据的收发效率,因为任何一个数据报文过来都要做匹配)

怎么找到对应的认证和关联的代码

这是一个比较重要的问题,我分析厂商的源代码。最后得出的结论是:认证和关联的代码是厂商自己实现的。 这个结论意味这linux内核没有提供一个通用的关联和认证的入口函数。
为了找到这两个函数,我们需要去在对应厂商的驱动代码中找。(注:一般情况下,无线的一些列扫描,认证,关联的处理函数都会在一个文件中。通过函数的名称来判断该函数所起到的作用,然后加DEBUG信息,可以确认该函数的功能)

  • 这里我也以rtl8197f驱动代码为例,我们来看看他的关联函数
static int rtl8192cd_query_psd_cfg80211(struct rtl8192cd_priv *priv, int chnl, int bw, int fft_pts);
#endif
static unsigned int OnAssocReq(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnProbeReq(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnProbeRsp(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnBeacon(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnDisassoc(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnAuth(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnDeAuth(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnWmmAction(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int DoReserved(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
#ifdef WDS
static void issue_probereq(struct rtl8192cd_priv * priv, unsigned char * ssid, int ssid_len, unsigned char * da);
#endif
#ifdef CLIENT_MODE
static unsigned int OnAssocRsp(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnBeaconClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnATIM(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnDisassocClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnAuthClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static unsigned int OnDeAuthClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo);
static void start_clnt_assoc(struct rtl8192cd_priv *priv);

从这里我们就可以看到上面我们的分析是没错的。通过这里函数的名称再结合函数的命名我们基本可以确认我们需要的函数是哪一个:**unsigned int OnAssocReq(struct rtl8192cd_priv priv, struct rx_frinfo pfrinfo)

为了进一步确认该函数是否是我们要找的关联函数,我们可以在该函数中添加打印。然后使用电脑或者手机去连接ap的无线,看看是否在连接过程中该函数会打印。

我们需要在该函数中做什么

这里最重要的一个问题就是,我们在该函数中应该怎么做?才能达到我们的需求。这里的思路就是在该函数中匹配mac,如果匹配上就直接drop掉该报文。

这里我们直接来看内核模块代码(内核模块代码是我自己写的)

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/types.h>typedef int (*fn_copy_mac_filter)(char *dst);
extern fn_copy_mac_filter copy_mac_filter;#define MAX_MAC_NUM 100/* mac filter链表 */
typedef struct _mac_filter {unsigned char mac[MAX_MAC_NUM][6];int mac_cnt;
} MAC_FILTER;MAC_FILTER mac_filter;unsigned char a2x(const char c);
int do_copy_mac_filter(MAC_FILTER *dst);spinlock_t info_lock;int hex2num(char c) {if (c >= '0' && c <= '9') return c - '0';if (c >= 'a' && c <= 'z') return c - 'a' + 10;if (c >= 'A' && c <= 'Z') return c - 'A' + 10;return 0;
}
int str2mac(char *pMac, const char *szMac) {const char *pTemp = szMac;int i = 0;for (i = 0; i < 6; i++) {pMac[i] = hex2num(*pTemp++) * 16;pMac[i] += hex2num(*pTemp++);}return 0;
}int do_copy_mac_filter(MAC_FILTER *dst) {int i = 0;int cnt = 0;spin_lock(&info_lock);cnt = mac_filter.mac_cnt;if (cnt <= 0) {spin_unlock(&info_lock);return -1;}dst->mac_cnt = cnt;
#if 1for (i = 0; i < mac_filter.mac_cnt; i++) {memcpy(dst->mac[i], mac_filter.mac[i], 6);
#if 0printk("%2x:%2x:%2x:%2x:%2x:%2x\n", dst->mac[i][0], dst->mac[i][1], \dst->mac[i][2], dst->mac[i][3], dst->mac[i][4], \dst->mac[i][5]);
#endif}#endifspin_unlock(&info_lock);return 0;
}static int write_mac_filter_proc(struct file *file, const char __user *buffer,unsigned long count, void *data) {char mac[16] = {0};char tmp[16] = {0};int cmd = -1;char *e = NULL;if (count < 0) return -1;spin_lock(&info_lock);strncpy(tmp, buffer, 2);cmd = simple_strtoull(tmp, &e, 10);/* 1是添加 2是删除 重复性检测由应用层做 */if (cmd == 1) {strncpy(mac, buffer + 2, sizeof(mac) - 1);str2mac(mac_filter.mac[mac_filter.mac_cnt], mac);mac_filter.mac_cnt++;copy_mac_filter = do_copy_mac_filter;}if (cmd == 2) {copy_mac_filter = NULL;memset(&mac_filter, 0, sizeof(mac_filter));}spin_unlock(&info_lock);return count;
}static int read_mac_filter_proc(struct file *file, char __user *buf,size_t count, loff_t *ppos) {int i;for (i = 0; i < mac_filter.mac_cnt; i++) {printk("cnt is %d\n", mac_filter.mac_cnt);printk("%2x:%2x:%2x:%2x:%2x:%2x", mac_filter.mac[i][0],mac_filter.mac[i][1], mac_filter.mac[i][2], mac_filter.mac[i][3],mac_filter.mac[i][4], mac_filter.mac[i][5]);printk("\n");}return 0;
}struct file_operations mac_filter_operations = {.open = seq_open,.read = read_mac_filter_proc,.write = write_mac_filter_proc,.owner = THIS_MODULE,
};static int mac_filter_init(void) {struct proc_dir_entry *pro = NULL;pro = proc_create("mac_filter", S_IFREG | S_IRWXU, 0, &mac_filter_operations);memset(&mac_filter, 0, sizeof(mac_filter));copy_mac_filter = do_copy_mac_filter;spin_lock_init(&info_lock);return 0;
}
static void mac_filter_exit(void) {copy_mac_filter = NULL;remove_proc_entry("mac_filter", 0);
}module_init(mac_filter_init);
module_exit(mac_filter_exit);
MODULE_LICENSE("GPL");
  • 第一步创建一个内核模块,定义MAX_MAC_NUM为最大的存储数据大小
  • 创建proc文件,将传入的mac转换成小写然后存储到数组中

OnAssocReq中代码实现(在驱动中添加我们内核模块对应的全局变量)

typedef struct _mac_filter{unsigned char mac[MAX_MAC_NUM][6];int mac_cnt;}MAC_FILTER;MAC_FILTER mac_filter;int (*copy_mac_filter)(MAC_FILTER *mac_filter) = NULL;
EXPORT_SYMBOL(copy_mac_filter);int mac_filter_get(MAC_FILTER* mac_filter)
{int ret = -1;memset(mac_filter,0,sizeof(MAC_FILTER));if (copy_mac_filter != NULL)ret = copy_mac_filter(mac_filter);return ret;
}

这段代码是定义在对应厂商的驱动中,主要是导出了copy_mac_filter符号。我们在内核模块加载的时候对该函数指针进行了一个赋值。如果内核模块加载,该符号就不为空。并且指向了内核模块中的do_copy_mac_filter函数。如果内核模块卸载,那么copy_mac_filter则为空。

接着我们来看看OnAssocReq中我们是怎么写的(将代码添加到驱动中)

unsigned int OnAssocReq(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo)
{struct wifi_mib        *pmib;struct stat_info  *pstat;unsigned char        *pframe, *p;unsigned char       rsnie_hdr[4]={0x00, 0x50, 0xf2, 0x01};
#ifdef RTL_WPA2unsigned char        rsnie_hdr_wpa2[2]={0x01, 0x00};
#endif
#ifdef HS2_SUPPORTunsigned char     rsnie_hdr_OSEN[4]={0x50, 0x6F, 0x9A, 0x12};
#endifint       len;
#ifndef SMP_SYNCunsigned long       flags;
#endifDOT11_ASSOCIATION_IND     Association_Ind;DOT11_REASSOCIATION_IND   Reassociation_Ind;unsigned char       supportRate[32];int                 supportRateNum;unsigned int     status = _STATS_SUCCESSFUL_;unsigned short     frame_type, ie_offset=0, val16;unsigned int z = 0;#ifdef P2P_SUPPORTunsigned char ReAssem_p2pie[MAX_REASSEM_P2P_IE];int IEfoundtimes=0;unsigned char *p2pIEPtr = ReAssem_p2pie ;int p2pIElen;
#endifpmib = GET_MIB(priv);pframe = get_pframe(pfrinfo);pstat = get_stainfo(priv, GetAddr2Ptr(pframe));/* yangpf add mac_filter */int i = 0;int ret = mac_filter_get(&mac_filter);if (pstat && ret == 0){for (i=0; i<mac_filter.mac_cnt; i++){if (memcmp(mac_filter.mac[i], pstat->hwaddr, 6) == 0)return 0;}}

我们可以看到这里分离出了sta的mac。然后将sta的mac和我们的进行对比。如果相等则直接返回。不会往下走。(相当于drop掉了关联的报文)。即可实现我们需要的功能。

关于无线的框架和数据报文的一些知识,本人也在积极的学习中,现在还是个小白。个人知识有限,欢迎大家一起学习交流。qq群:610849576

无线黑名单实现(将终端踢下线同时禁止终端再次连接)相关推荐

  1. 单人登录-踢下线功能实现

    单人登录-踢下线功能实现 功能描述: 用户在不同会话层登录账号会将之前的账户状态注销,同一时间只有一个用户在线. 实现:servlet+redis, 1.由于session的存储形式类似于key-va ...

  2. Java用Filter制作登录限制-踢下线防踢等

    Hello, 我是Shendi, 这次我给大家带来了 JavaWeb登录 限制登录 防踢  挤下线的功能实现 如题,很简单,我们需要编写一个Filter,就叫LoginFilter  实现javax包 ...

  3. Android单点登录,互踢下线代码实现

    Android单点登录,互踢下线代码实现 分享一个在项目中必然会用到的小功能--单点登录,也就是我们常说的互踢下线. 国际惯例,先上效果图 一.先说逻辑,其实挺简单 ​ 首先,对于监听账号是否在其他设 ...

  4. [4G+5G专题-140]: 终端 - 5G终端主要的产品形态 - 行业终端

    作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址:https://blog.csdn.net/HiWangWenBing/article/detai ...

  5. Lora和Zigbee无线通讯技术的对比(哪种技术更适合物联网连接)

    Lora和Zigbee无线通讯技术的对比(哪种技术更适合物联网连接) ZigBee是基于IEEE802.15.4标准的低功耗局域网协议,LoRa是LPWAN通信技术中的一种,那么lora技术和ZigB ...

  6. 安装终端服务和终端服务授权,激活终端服务授权

    1.1 安装和配置终端服务 1.1.1 安装终端服务授权 在DCServer安装终端服务器授权,给域中的终端服务器分发终端服务器许可.没有做指定终端服务授权的终端服务器,只能让用户使用120天. 步骤 ...

  7. 终端、虚拟控制台与伪终端

    (1)在本机上登录字符界面或者X11图形界面均为tty终端 (2)通过telnet/ssh远程登录或者在X11中生成一个XTERM的终端,均为虚拟终端PTS. 如: [lujinhong@localh ...

  8. linux怎么将终端一分为二,Linux下的终端和作业控制

    一.进程间的关系 进程间的三种关系:进程组.作业和会话. 1.进程组 每个进程除了有一个进程ID之外,还属于一个进程组.进程组是一个或多个进程的集合.通常,它们与同一作业相关联,可以接收来自同一终端的 ...

  9. 2022 极术通讯-安谋科技参与起草的PSA相关物联网终端安全标准介绍(电信终端产业协会发布)

    首发极术社区.如对Arm相关技术感兴趣,欢迎私信 aijishu20加入技术微信群.导读:极术通讯引入行业媒体和技术社区.咨询机构优质内容,定期分享产业技术趋势与市场应用热点. 芯方向 • 安谋科技参 ...

最新文章

  1. 12306 背后的技术大牛:我不跟人拼智商,我就跟他们拼狠!
  2. 中小型商业银行的软件安全测试之道
  3. 总结一下嵌入式OLED显示屏显示中文汉字的办法
  4. Android localsocket 的基础和使用实践: 01
  5. 网站设置404错误页
  6. webservice CXF入门服务端
  7. order by 影响效率么_内存碎片对性能的潜在影响
  8. layui遇见的问题
  9. 0308·付费专栏销售排行榜
  10. excel公式编辑器_办公软件操作技巧035:如何在excel中输入n次方
  11. java垃圾回收策论,share_doucument/jvm的垃圾回收策略.md at develop · LiuLei0571/share_doucument · GitHub...
  12. 笔记本显卡和台式显卡区别介绍
  13. 设计一个Dog类,包含名字,年龄,颜色三个属性
  14. 网红奶茶品牌茶颜悦色,开业仅半小时就停业,黄牛价200元一杯
  15. oracle crs 4563,重启机器后,节点2无法启动crs,Oracle你生产的RAC为何如此的脆弱,有图有真相。求解...
  16. Python 爬虫 | 获取历史涨停数据
  17. java 搞笑翻译_那些让我们哭笑不得的爆笑翻译!佩服网友的脑洞!
  18. 实时即未来,大数据项目车联网之原始数据实时ETL任务HBase调优【九】
  19. 『转】山世光导师致报考研究生的一封信
  20. 使用leaflet仿原神提瓦特大地图制作日记

热门文章

  1. Kubernetes集群(k8s)- 介绍和部署
  2. 判断文档是office打开,还是WPS打开
  3. Android开发_Animation简单介绍
  4. 银河麒麟Linux操作系统报错:U盘---只读文件系统
  5. ubuntu16.04下安装docker
  6. Unity开源的webrtc库,为流式远程渲染提供视频流传输方案
  7. python:cmath --- 关于复数的数学函数
  8. 中国象棋程序的设计与实现(九)–棋子点,棋子的小窝
  9. 为什么里程碑很重要?
  10. 微信公众号如何接入Java后台