在前面两篇文章中详细介绍了pptp vpn的安装与使用,以及如何配置用户认证存入mysql数据库。本文将在前面两篇文章的基础上介绍如何对用户的流量做限制,同时限制相同账号的用户,同一时刻的在线数为1。

前文传送门地址:

PPTP-VPN部署与简单使用   http://ylw6006.blog.51cto.com/470441/1794577

PPTP-VPN使用mysql进行用户登录认证 http://ylw6006.blog.51cto.com/470441/1795201

一、向mysql库表中插入基础数据

1
2
3
4
5
6
7
8
mysql> use radius
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Auth-Type',':=','Local'); 
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Service-Type',':=','Framed-User'); 
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Framed-IP-Address',':=','255.255.255.255'); 
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Framed-IP-Netmask',':=','255.255.255.0'); 
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Acct-Interim-Interval',':=','600');
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Max-Monthly-Traffic',':=','20480'); 
mysql> INSERT INTO radgroupcheck (groupname,attribute,op,VALUE) VALUES ('user','Simultaneous-Use',':=','1');

acct-interim-interval是计算流量的间隔(600秒),意味着每隔10分钟记录当前流量;

Max-Monthly-Traffic是每月最大流量,这里是20G(单位是M);

radgroupcheck表的Simultaneous-Use表示单个用户的同时连接数目;

这里要格外注意的是,许多网络上的文章介绍Max-Monthly-Traffic单位为字节,数值为5368709102,换算一下大概5G左右,而如果我们也精确到字节,数值设为20G,也就是21474836480,则用户拨入进行身份验证的时候将会报错。因而此次我们将流量限制的精度单位修改为M。详细可参考如下链接介绍:http://www.xj123.info/2856.html

二、修改配置文件

1、修改/etc/raddb/sites-enabled/default文件,添加流量限制的reject条件

1
2
3
4
5
6
7
8
# vi  /etc/raddb/sites-enabled/default 
#找到authorize一节插入如下内容:
update request { 
    Group-Name := "%{sql:SELECT groupname FROM radusergroup WHERE username='%{User-Name}' ORDER BY priority}" 
    
    if ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") { 
    reject 
    }

2、由于使用了非内置的attribute Max-Monthly-Traffic,所以需要在/etc/raddb/dictionary里面定义

1
2
# tail -1 /etc/raddb/dictionary 
ATTRIBUTE       Max-Monthly-Traffic     3003    integer

3、修改/etc/raddb/sql/mysql/dialup.conf文件,开启在线用户数检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# vi  /etc/raddb/sql/mysql/dialup.conf 
sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}}"
#sql_user_name = "%{User-Name}"  #注释掉这行
  
# Uncomment simul_count_query to enable simultaneous use checking 
        simul_count_query = "SELECT COUNT(*) \
                             FROM ${acct_table1} \
                             WHERE username = '%{SQL-User-Name}' \
                             AND acctstoptime IS NULL"
  
        simul_verify_query  = "SELECT radacctid, acctsessionid, username, \
                               nasipaddress, nasportid, framedipaddress, \
                               callingstationid, framedprotocol \
                               FROM ${acct_table1} \
                               WHERE username = '%{SQL-User-Name}' \
                               AND acctstoptime IS NULL"

三、重启服务

# /etc/init.d/radiusd stop

# /etc/init.d/pptpd restart

四、测试

1、将rediusd服务运行在debug模式下,进行拨号测试,主要测试流量控制!

#radiusd -X

通过上面可以看到当前的用户流量消耗为2M,限制流量的值为20480M。

因而在/etc/raddb/sites-enabled/default文件,判断流量限制的reject条件的结果为false,用户可以通过验证,完成拨号!下面是详细的拨号日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
rad_recv: Access-Request packet from host 127.0.0.1 port 49226, id=94, length=150
        Service-Type = Framed-User
        Framed-Protocol = PPP
        User-Name = "ptest1"
        MS-CHAP-Challenge = 0x6716c32940f1c84ad213d2d52df1712d
        MS-CHAP2-Response = 0x2400c77c090296803fb3c0822b8c679547f000000000000000001eb41fe8e518c1f756fb5d9d5904ddb8dc1fe271e98aa055
        Calling-Station-Id = "27.151.123.121"
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 0
# Executing section authorize from file /etc/raddb/sites-enabled/default
+group authorize {
++update request {
sql_xlat
        expand: %{Stripped-User-Name} -> 
        ... expanding second conditional
        expand: %{User-Name} -> ptest1
        expand: %{%{User-Name}:-DEFAULT} -> ptest1
        expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
sql_set_user escaped user --> 'ptest1'
        expand: SELECT groupname FROM radusergroup WHERE username='%{User-Name}' ORDER BY priority -> SELECT groupname FROM radusergroup WHERE username='ptest1' ORDER BY priority
rlm_sql (sql): Reserving sql socket id: 30
sql_xlat finished
rlm_sql (sql): Released sql socket id: 30
        expand: %{sql:SELECT groupname FROM radusergroup WHERE username='%{User-Name}' ORDER BY priority} -> user
++} # update request = noop
++? if ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}")
sql_xlat
        expand: %{Stripped-User-Name} -> 
        ... expanding second conditional
        expand: %{User-Name} -> ptest1
        expand: %{%{User-Name}:-DEFAULT} -> ptest1
        expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
sql_set_user escaped user --> 'ptest1'
        expand:  SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now()); ->  SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='ptest1' AND date_format(acctstarttime, '2016-06-30') >= date_format(now(),'2016-06-01') AND date_format(acctstoptime, '2016-06-30') <= last_day(now());
rlm_sql (sql): Reserving sql socket id: 29
sql_xlat finished
rlm_sql (sql): Released sql socket id: 29
        expand: %{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());} -> 2
sql_xlat
        expand: %{Stripped-User-Name} -> 
        ... expanding second conditional
        expand: %{User-Name} -> ptest1
        expand: %{%{User-Name}:-DEFAULT} -> ptest1
        expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
sql_set_user escaped user --> 'ptest1'
        expand:  SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic'; ->  SELECT value FROM radgroupreply WHERE groupname='user' AND attribute='Max-Monthly-Traffic';
rlm_sql (sql): Reserving sql socket id: 28
sql_xlat finished
rlm_sql (sql): Released sql socket id: 28
        expand: %{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';} -> 20480
? Evaluating ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") -> FALSE
++? if ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") -> FALSE
++[preprocess] = ok
++[chap] = noop
[mschap] Found MS-CHAP attributes.  Setting 'Auth-Type  = mschap'
++[mschap] = ok
++[digest] = noop
[suffix] No '@' in User-Name = "ptest1", looking up realm NULL
[suffix] No such realm "NULL"
++[suffix] = noop
[eap] No EAP-Message, not doing EAP
++[eap] = noop
[sql]   expand: %{Stripped-User-Name} -> 
[sql]   ... expanding second conditional
[sql]   expand: %{User-Name} -> ptest1
[sql]   expand: %{%{User-Name}:-DEFAULT} -> ptest1
[sql]   expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
[sql] sql_set_user escaped user --> 'ptest1'
rlm_sql (sql): Reserving sql socket id: 27
[sql]   expand: SELECT id, username, attribute, value, op           FROM radcheck           WHERE username = '%{SQL-User-Name}'           ORDER BY id -> SELECT id, username, attribute, value, op           FROM radcheck           WHERE username = 'ptest1'           ORDER BY id
WARNING: Found User-Password == "...".
WARNING: Are you sure you don't mean Cleartext-Password?
WARNING: See "man rlm_pap" for more information.
[sql] User found in radcheck table
[sql]   expand: SELECT id, username, attribute, value, op           FROM radreply           WHERE username = '%{SQL-User-Name}'           ORDER BY id -> SELECT id, username, attribute, value, op           FROM radreply           WHERE username = 'ptest1'           ORDER BY id
[sql]   expand: SELECT groupname           FROM radusergroup           WHERE username = '%{SQL-User-Name}'           ORDER BY priority -> SELECT groupname           FROM radusergroup           WHERE username = 'ptest1'           ORDER BY priority
[sql]   expand: SELECT id, groupname, attribute,           Value, op           FROM radgroupcheck           WHERE groupname = '%{Sql-Group}'           ORDER BY id -> SELECT id, groupname, attribute,           Value, op           FROM radgroupcheck           WHERE groupname = 'user'           ORDER BY id
[sql] User found in group user
[sql]   expand: SELECT id, groupname, attribute,           value, op           FROM radgroupreply           WHERE groupname = '%{Sql-Group}'           ORDER BY id -> SELECT id, groupname, attribute,           value, op           FROM radgroupreply           WHERE groupname = 'user'           ORDER BY id
rlm_sql (sql): Released sql socket id: 27
++[sql] = ok
++[expiration] = noop
++[logintime] = noop
[pap] WARNING: Auth-Type already set.  Not setting to PAP
++[pap] = noop
+} # group authorize = ok
Found Auth-Type = MSCHAP
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!    Replacing User-Password in config items with Cleartext-Password.     !!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!! Please update your configuration so that the "known good"               !!!
!!! clear text password is in Cleartext-Password, and not in User-Password. !!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Executing group from file /etc/raddb/sites-enabled/default
+group MS-CHAP {
[mschap] Creating challenge hash with username: ptest1
[mschap] Client is using MS-CHAPv2 for ptest1, we need NT-Password
[mschap] adding MS-CHAPv2 MPPE keys
++[mschap] = ok
+} # group MS-CHAP = ok
# Executing section session from file /etc/raddb/sites-enabled/default
+group session {
[radutmp]       expand: /var/log/radius/radutmp -> /var/log/radius/radutmp
++[radutmp] = ok
+} # group session = ok
# Executing section post-auth from file /etc/raddb/sites-enabled/default
+group post-auth {
[sql]   expand: %{Stripped-User-Name} -> 
[sql]   ... expanding second conditional
[sql]   expand: %{User-Name} -> ptest1
[sql]   expand: %{%{User-Name}:-DEFAULT} -> ptest1
[sql]   expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
[sql] sql_set_user escaped user --> 'ptest1'
[sql]   expand: %{User-Password} -> 
[sql]   ... expanding second conditional
[sql]   expand: %{Chap-Password} -> 
[sql]   expand: INSERT INTO radpostauth                           (username, pass, reply, authdate)                           VALUES (                           '%{User-Name}',                           '%{%{User-Password}:-%{Chap-Password}}',                           '%{reply:Packet-Type}', '%S') -> INSERT INTO radpostauth                           (username, pass, reply, authdate)                           VALUES (                           'ptest1',                           '',                           'Access-Accept', '2016-06-30 13:05:14')
rlm_sql (sql) in sql_postauth: query is INSERT INTO radpostauth                           (username, pass, reply, authdate)                           VALUES (                           'ptest1',                           '',                           'Access-Accept', '2016-06-30 13:05:14')
rlm_sql (sql): Reserving sql socket id: 26
rlm_sql (sql): Released sql socket id: 26
++[sql] = ok
++[exec] = noop
+} # group post-auth = ok
Sending Access-Accept of id 94 to 127.0.0.1 port 49226
        Service-Type := Framed-User
        Framed-IP-Address := 255.255.255.255
        Framed-IP-Netmask := 255.255.255.0
        Acct-Interim-Interval := 600
        MS-CHAP2-Success = 0x24533d46303044303641413737333432343231363234364143413245333041373133433531344439353037
        MS-MPPE-Recv-Key = 0x3373da01475488084e5f82abae7cbda8
        MS-MPPE-Send-Key = 0xdb408d5d7f18d9fd38e6c1888b8c0b13
        MS-MPPE-Encryption-Policy = 0x00000001
        MS-MPPE-Encryption-Types = 0x00000006
Finished request 0.
Going to the next request
Waking up in 4.9 seconds.
Cleaning up request 0 ID 94 with timestamp +88
Ready to process requests.
rad_recv: Accounting-Request packet from host 127.0.0.1 port 58801, id=95, length=114
        Acct-Session-Id = "5774A890092400"
        User-Name = "ptest1"
        Acct-Status-Type = Start
        Service-Type = Framed-User
        Framed-Protocol = PPP
        Calling-Station-Id = "27.151.123.121"
        Acct-Authentic = RADIUS
        NAS-Port-Type = Async
        Framed-IP-Address = 192.168.222.10
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 0
        Acct-Delay-Time = 0
# Executing section preacct from file /etc/raddb/sites-enabled/default
+group preacct {
++[preprocess] = ok
[acct_unique] WARNING: Attribute NAS-Identifier was not found in request, unique ID MAY be inconsistent
[acct_unique] Hashing 'NAS-Port = 0,,NAS-IP-Address = 127.0.0.1,Acct-Session-Id = "5774A890092400",User-Name = "ptest1"'
[acct_unique] Acct-Unique-Session-ID = "413ac0cc5b5f4759".
++[acct_unique] = ok
[suffix] No '@' in User-Name = "ptest1", looking up realm NULL
[suffix] No such realm "NULL"
++[suffix] = noop
+} # group preacct = ok
# Executing section accounting from file /etc/raddb/sites-enabled/default
+group accounting {
[detail]        expand: %{Packet-Src-IP-Address} -> 127.0.0.1
[detail]        expand: /var/log/radius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/detail-%Y%m%d -> /var/log/radius/radacct/127.0.0.1/detail-20160630
[detail] /var/log/radius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/detail-%Y%m%d expands to /var/log/radius/radacct/127.0.0.1/detail-20160630
[detail]        expand: %t -> Thu Jun 30 13:05:20 2016
++[detail] = ok
[sql]   expand: %{Stripped-User-Name} -> 
[sql]   ... expanding second conditional
[sql]   expand: %{User-Name} -> ptest1
[sql]   expand: %{%{User-Name}:-DEFAULT} -> ptest1
[sql]   expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
[sql] sql_set_user escaped user --> 'ptest1'
[sql]   expand: %{Acct-Delay-Time} -> 0
[sql]   expand:            INSERT INTO radacct             (acctsessionid,    acctuniqueid,     username,              realm,            nasipaddress,     nasportid,              nasporttype,      acctstarttime,    acctstoptime,              acctsessiontime,  acctauthentic,    connectinfo_start,              connectinfo_stop, acctinputoctets,  acctoutputoctets,              calledstationid,  callingstationid, acctterminatecause,              servicetype,      framedprotocol,   framedipaddress,              acctstartdelay,   acctstopdelay,    xascendsessionsvrkey)           VALUES             ('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}',              '%{SQL-User-Name}',              '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}',              '%{NAS-Port-Type}', '%S', NULL,              '0', '%{Acct-Authentic}', '%{Connect-Info}',              '', '0', '0',              '%{Called-Station-Id}', '%{Calling-Station-Id}', '',              '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}',      
rlm_sql (sql): Reserving sql socket id: 25
rlm_sql (sql): Released sql socket id: 25
++[sql] = ok
++[exec] = noop
[attr_filter.accounting_response]       expand: %{User-Name} -> ptest1
attr_filter: Matched entry DEFAULT at line 12
++[attr_filter.accounting_response] = updated
+} # group accounting = updated
Sending Accounting-Response of id 95 to 127.0.0.1 port 58801
Finished request 1.
Cleaning up request 1 ID 95 with timestamp +94
Going to the next request
Ready to process requests.

2、测试同一个VPN账号,多终端登录

通过如下sql语句可以看到当前用户的拨号连接情况,很明显通过前面的配置,并没有起到限制的效果。

1
2
mysql> SELECT radacctid, acctsessionid, username,nasipaddress, nasportid, framedipaddress, callingstationid, framedprotocol FROM  radacct WHERE username ='yang' AND acctstoptime IS NULL;
mysql> SELECT COUNT(*) from radacct WHERE username ='yang' AND acctstoptime IS NULL;

通过修改/etc/raddb/sites-enabled/default文件,注释掉session节的radutmp配置,重启radiusd服务后测试,发现效果符合预期

# vi /etc/raddb/sites-enabled/default

同一个账号的第二个拨号连接就会直接提示验证失败!

PPTP-VPN第三章——用户流量与并发数限制的更多相关文章

  1. (转)iOS Wow体验 - 第三章 - 用户体验的差异化策略

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第三章译文精选,其余章节将陆续放出.上一篇:Wow ...

  2. Testlink1.9.17使用方法( 第三章 初始配置[配置用户、产品] )

    第三章 初始配置(配置用户.产品) 一. 设置用户 QQ交流群:585499566 在TestLink系统中,每个用户都可以维护自己的私有信息.admin可以创建用户,但不能看到其它用户的密码.在用户 ...

  3. Gradle2.0用户指南翻译——第三章. 教程

    翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc本文翻译所在分支:https://github.com/msdx/gradledoc/tree/2 ...

  4. 2017.2.28 activiti实战--第五章--用户与组及部署管理(三)部署流程及资源读取

    学习资料:<Activiti实战> 第五章 用户与组及部署管理(三)部署流程及资源读取 内容概览:如何利用API读取已经部署的资源,比如读取流程定义的XML文件,或流程对应的图片文件. 以 ...

  5. CentOS 6.5搭建PPTP VPN服务器

    VPN是虚拟专用网络(Virtual Private Network)的缩写,VPN有多种分类方式,包括PPTP.L2TP.IPSec等,本文配置的VPN服务器是采用PPTP协议的,PPTP是在PPP ...

  6. 精通Web Analytics 2.0 (5) 第三章:点击流分析的奇妙世界:指标

    精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第三章:点击流分析的奇妙世界:指标 新的Web Analytics 2.0心态:搞定它.新的闪亮系列工具:是的.准备好了吗?当然 ...

  7. ubuntu 搭建PPTP VPN服务器

    上一篇文章介绍了如何在Ubuntu服务器上搭建IPSEC L2TP VPN服务器.继续介绍如何在Ubuntu服务器上搭建PPTP VPN服务器. 首先安装以下所需包 #apt-get install ...

  8. 转载 - Vultr VPS注册开通且一键快速安装PPTP VPN和电脑连接使用

    本文转载来自:https://www.vultrclub.com/139.html 从2014年Vultr VPS进入市场之后,作为有背景.实力的搅局者,是的最近两年VPS.服务器的用户成本降低.配置 ...

  9. SEO 第三章

    SEO第三章 本次课目标: 1.  掌握关键词的选取方法 2.  掌握关键词的竞争强度分析 3.  掌握关键词的拓展方法 一.关键词的选取 选择关键词的时候可以根据公司网站的定位,围绕公司的主营产品或 ...

随机推荐

  1. jQuery的编码标准和最佳实践

    不知道在哪里看到了这篇关于jQuery编码的文章,挺实用的,恰好最近在研究jQuery的基础知识,今天打开收藏夹来翻译一下,原文的英语不难,但是内容很实用,可能有大神已经翻译过了,大家看精华就行了. ...

  2. .net工作准备系列--01前言

    注:学习参考朱毅编著的进入IT名企必读200题. 内容重在自我学习与巩固. 前言: 章节划分 01应聘须知 02基础知识(重点) 03进阶知识 04重点应用(aspnet第一部分) 04重点应用(as ...

  3. 杭电acm 1001

    #include<cstdio> int main() { int n; while(scanf("%d",&n)!=EOF) { ==) printf(*(n ...

  4. qt之mapx组件编程c2248和c2512错误

    mapx组件利用qt工具dumpcpp到处头文件和.cpp文件后将其加入到新建的qt项目中即可. 不过本人遇到问题知道今天偶然的解决了.记下来,以免忘记. demo的项目结构如下: 然后在.pro文件 ...

  5. 1 《JavaScript高级程序设计》学习笔记(1)

    欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 首先,我将从<JavaScript高级程序设计>这本JavaScript学习者必看的经典教 ...

  6. 网络转载——java接口的概念

    为什么会出现接口? 接口的出现是为了扩展java中的类继承的单调性.这样使得功能更加丰富. 接口关键字? 定义接口interface,实现一个接口  implements 什么接口呢? 接口是一种特殊 ...

  7. click 事件 arguments.callee 每次点击自动* 2

    今天在测试JQUERY(版本3.0,向下兼容3.0)时发现一个很特别的现象,代码如下: $($('button').get(4)).click(function(){ alert($(this).ht ...

  8. PIC32MZ tutorial -- Core Timer

    Core Timer is a very popular feature of PIC32 since it is a piece of the MIPS M4K core itself and is ...

  9. sql 用union合并合并查询结果

    合并操作与连接相似,因为他们都是将两个表合并起来的另一个表的方法,然而他们的合并方法有本质的区别, 合并是两个表的相加,连接时时两个表的相乘: 01 在合并中两个表原列的数量与数据类型必须相同:在连接 ...

  10. 一个C#语法高亮插件

    语法高亮对程序员阅读代码来说有着不小的帮助,虽然VisualStudio本身支持C#语法高亮,但也只是对关键字.类名.字符串等少数元素加了标记,而我们代码中主题:变量.函数.属性.事件等都没有进行高亮 ...