PPTP-VPN第三章——用户流量与并发数限制
在前面两篇文章中详细介绍了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第三章——用户流量与并发数限制的更多相关文章
- (转)iOS Wow体验 - 第三章 - 用户体验的差异化策略
本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第三章译文精选,其余章节将陆续放出.上一篇:Wow ...
- Testlink1.9.17使用方法( 第三章 初始配置[配置用户、产品] )
第三章 初始配置(配置用户.产品) 一. 设置用户 QQ交流群:585499566 在TestLink系统中,每个用户都可以维护自己的私有信息.admin可以创建用户,但不能看到其它用户的密码.在用户 ...
- Gradle2.0用户指南翻译——第三章. 教程
翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc本文翻译所在分支:https://github.com/msdx/gradledoc/tree/2 ...
- 2017.2.28 activiti实战--第五章--用户与组及部署管理(三)部署流程及资源读取
学习资料:<Activiti实战> 第五章 用户与组及部署管理(三)部署流程及资源读取 内容概览:如何利用API读取已经部署的资源,比如读取流程定义的XML文件,或流程对应的图片文件. 以 ...
- CentOS 6.5搭建PPTP VPN服务器
VPN是虚拟专用网络(Virtual Private Network)的缩写,VPN有多种分类方式,包括PPTP.L2TP.IPSec等,本文配置的VPN服务器是采用PPTP协议的,PPTP是在PPP ...
- 精通Web Analytics 2.0 (5) 第三章:点击流分析的奇妙世界:指标
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第三章:点击流分析的奇妙世界:指标 新的Web Analytics 2.0心态:搞定它.新的闪亮系列工具:是的.准备好了吗?当然 ...
- ubuntu 搭建PPTP VPN服务器
上一篇文章介绍了如何在Ubuntu服务器上搭建IPSEC L2TP VPN服务器.继续介绍如何在Ubuntu服务器上搭建PPTP VPN服务器. 首先安装以下所需包 #apt-get install ...
- 转载 - Vultr VPS注册开通且一键快速安装PPTP VPN和电脑连接使用
本文转载来自:https://www.vultrclub.com/139.html 从2014年Vultr VPS进入市场之后,作为有背景.实力的搅局者,是的最近两年VPS.服务器的用户成本降低.配置 ...
- SEO 第三章
SEO第三章 本次课目标: 1. 掌握关键词的选取方法 2. 掌握关键词的竞争强度分析 3. 掌握关键词的拓展方法 一.关键词的选取 选择关键词的时候可以根据公司网站的定位,围绕公司的主营产品或 ...
随机推荐
- linux_oracle_healthcheck.sh
#!/bin/bash######################################################################################### ...
- (原)android4.2以后获取应用程序和缓存大小的方法(源码有改变)
以前获取应用的大小是用 PackageManager mPackageManager= getPackageManager(); try {Method getPackageSizeInfoMetho ...
- php源码之遍历目录下的所有的文件
<?php //遍历目录下的所有的文件 -- 递归调用 // http://www.manongjc.com/article/1495.html function get_all_file1($ ...
- python 核心编程课后练习(chapter 6)
6-1 #6-1 #help(string) import string str = "helloworld" substr = "h1e" if string ...
- ZAM 3D 制作简单的3D字幕 流程(二)
原地址:http://www.cnblogs.com/yk250/p/5663907.html 文中表述仅为本人理解,若有偏差和错误请指正! 接着 ZAM 3D 制作简单的3D字幕 流程(一) .本篇 ...
- Shuffling Machine和双向链表
1. 双向链表 https://github.com/BodhiXing/Data_Structure 2. Shuffling Machine https://pta.patest.cn/pta/t ...
- iOS开发-- RunLoop的基本概念与例子分析
看了一下,上一篇貌似5个月前的
- 关于iOS地图定位中点击设置->隐私->定位服务 闪退问题
iOS8之后,如果应用中用到了地图定位,那么点击设置->隐私->定位服务 再点击该应用有时候会出现闪退问题,其原因是iOS8之后定位中添加了 NSLocationWhenInUseDesc ...
- eclipse内嵌jetty(run-jetty-run插件) 配置jndi数据源
运行环境 java 6,eclipse juno,ssh(spring,hibernate,springmvc ) 1.离线安装 下载地址:http://pan.baidu.com/s/1qX67wO ...
- 轻松获取LAMP或LNMP环境编译参数
查看web服务的编译参数 1. 查看nginx的编译参数: /apps/nginx/sbin/nginx -V 范例: [root@VM- ~]# /apps/nginx/sbin/nginx -V ...