简单的统计PHP源码
find . -name “*.php” | xargs cat | sed ‘s/^[[:space:]]*//g’ | sed ‘/^[[:space:]]*$/d’ | grep -E -v “^/|^*” | wc -l
删除空行,过滤注释
find . -name “*.php” | xargs cat | sed ‘s/^[[:space:]]*//g’ | sed ‘/^[[:space:]]*$/d’ | grep -E -v “^/|^*” | wc -l
删除空行,过滤注释
系统:
Red Hat Enterprise Linux Server release 5.1 (Tikanga)
短信猫:
Wavecom M1306B USB接口
工具:
smstools3
http://smstools3.kekekasvi.com/
配置文件:
# Example smsd.conf. Read the manual for a description
devices = GSM1
logfile = /var/log/smsd.log
loglevel = 7
outgoing = /var/spool/sms/outgoing
checked = /var/spool/sms/checked
failed = /var/spool/sms/failed
incoming = /var/spool/sms/incoming
#sent = /var/spool/sms/sent
receive_before_send = no
[GSM1]
#init = AT+CPMS="SM","SM"
#pre_init = no
#init = ATE1;+CPMS="SM","SM"
device = /dev/ttyUSB1
#device = /dev/usb/ttyUSB0
#device = /dev/ttyS0
incoming = no
#pin = 1111
mode = new
rtscts = yes
cs_convert = yes
memory_start=1
report = no
send_delay = 0
baudrate = 115200
#baudrate = 9600
#queues = OTHER
相关文档:
http://smstools3.kekekasvi.com/index.php?p=hardwarecomp
http://www.ozekisms.com/index.php?ow_page_number=380
[root@databak1 smstools3]# make install
cd src && make -
make[1]: Entering directory `/data1/soft/smstools3/src'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/data1/soft/smstools3/src'
./install.sh /usr/local/bin
Installing binary program files
/usr/local/bin/smsd
Installing some scripts
/usr/local/bin/sendsms
/usr/local/bin/sms2html
/usr/local/bin/sms2unicode
/usr/local/bin/unicode2sms
Installing config file
/etc/smsd.conf
Creating minimum spool directories
Skipped /var/spool, directory already exists
Creating directory /var/spool/sms
Creating directory /var/spool/sms/incoming
Creating directory /var/spool/sms/outgoing
Creating directory /var/spool/sms/checked
Installing start-script
/etc/init.d/sms3
Example script files are not installed automatically.
Please dont forget to edit /etc/smsd.conf.
pl2303 6-2:1.0: pl2303 converter detected
usb 6-2: pl2303 converter now attached to ttyUSB0
usbcore: registered new driver pl2303
drivers/usb/serial/pl2303.c: Prolific PL2303 USB to serial adaptor driver
垃圾邮件过滤器通常根据电子邮件来源或内容来判断邮件是不是垃圾邮件,并阻断约20%的电子邮件营销信息,绝大多数则由客户决定其是否为垃圾邮件:如果用户对消息的投诉比例超过了一定的阈值,通常是1%-2%,则大多数ISP将把这个消息的发送方标记为垃圾邮件发送方。
ISP电子邮件进行特征考察的方法是众多的,因此不存在标准。
随着垃圾邮件越来越泛滥,世界上所有的ISP和服务器提供商都采取了越来越严厉的垃圾邮件过滤规则,即使是正在的、合理合法的用户邮件或者电子邮件营销,也有可能进入垃圾信箱,我们要做的就是了解垃圾邮件过滤规则,尽量避免进入垃圾信箱。
l 以触发式的过滤算法鉴别垃圾邮件
这 种过滤器通常已经安装在电子邮件客户端软件或者邮件服务器上,其原理是过滤软件检查邮件发送人、标题、正文内容,以及邮件中出现的链接和域名,甚至电话号 码。当发现带明显广告性质,或者经常出现已知垃圾邮件的典型特征,则给这封邮件打一定的垃圾邮件特征分数。当分数达到一定数值时,邮件将被标志为垃圾邮 件,直接过滤到垃圾邮件文件夹。
比如,邮件标题中出现¥、$符号,可以给予2分垃圾邮件分数。邮件内容中出现“免费”、“发票”、“促销”等典型垃圾邮件中经常出现的词汇时,也各给予1分。邮件中如果包含已经被确认为经常发送垃圾邮件的域名,再加1分。甚至邮件内容中出现被确认与垃圾邮件相关的电话号码,也给个分数。当这些垃圾分数相加达到某一个数值时,比如达到10分,这个邮件将被标志为垃圾。
l 以黑名单为基础
有些创建和维护链接邮件黑名单的组织,专门接受用户的垃圾邮件投诉,如果确认确实是垃圾邮件,黑名单运行者将把发送垃圾邮件的服务器和用户IP地址放入黑名单。
有时候用户投诉,其实并不是真实的以为所收到的邮件是垃圾邮件,而是用户忘记了曾经注册过这个电子杂志。如果你的IP地址被错误的投诉而列入黑名单,唯一的办法是联系黑名单维护组织,说明情况,提出证据,要求把你的IP地址从黑名单中删除。不过这个过程非常复杂。
l 邮件防火墙
很多大公司的邮件服务器是运行在邮件防火墙之后,这些防火墙会共同地使用各种过滤器和黑名单,再加上自行研究的一些算法,来鉴别和剔除垃圾邮件。这些防火墙的算法更复杂,并且不与他人分享细节,对正常的邮件送达也可能有致命的影响。
l 避免利用"收件人"、"抄送"和"暗送"将一封邮件发给大量的接收者
确信一封邮件每次仅发给了一个人。同样的邮件发送给多人往往会有一部分人是不需要接收该邮件的。这样会容易被视为发送垃圾邮件。
l 选择一个能够使人信任的主题
避免使用垃圾邮件常用的单词和符号,例如“免费”“派送”、“优惠”、“代开发票”以及怪异字符等标点文字。
l 在电子邮件中含有"退订"的超链接
是不是垃圾邮件由收件人最终决定。如果他们不希望收到您发送的电子邮件,很可能会投诉。所以,一旦用户退订邮件,应立即停止发送。
l 立即停止向被收件人拒绝过的邮件地址发送邮件
如果一味地给拒绝响应人员发送电子邮件,电子邮件地址可能会失效,某些ISP会保留失效的电子邮件地址来捕获垃圾邮件。
l 要求对方加入白名单
l 提醒收件人为什么会接到您发送的电子邮件
例如“您在大蒜节上订阅了这个时事通讯月刊。”同时附带确认链接。
l 分批发送电子邮件并使用多台发送服务器
1. 设置一个有A记录的Hostname
邮件系统一般使用操作系统的Hostname作为SMTP会话中HELO指令后面的内容,而某些比较严格的过滤系统会要求HELO内容是有A记录的域名,且与来源IP匹配。所以将Hostname设置为一个有A记录的域名,而且A记录就指向邮件服务器所在的IP,这将会减少在HELO阶段就被接收方拒绝的机会。
2. 检查你的IP地址的信誉度,如果有可能尽量购买整个C段的IP地址
检查你的邮件服务器所在IP地址是否在国外的RBL组织的黑名单中,到www.dnsstuff.com网站,可以一次性查询某个IP是否在各个主要的RBL组织的黑名单中。如果,你的IP被列入了黑名单,则应该检查下面所说的3和4点,即时采取措施,如果你是因为同一个C段的其他IP被牵连进入黑名单,则应该把这个问题向你的ISP(IDC机房)反映,要求他们采取行动清理垃圾源并且及时与RBL组织交涉。
对于有能力的公司,应该采购整一个C段的IP地址,尽量避免与别的邮件服务器混用同一个C段的IP。
3. 禁止Open Relay
Open Relay(第三方转发)就是说允许发件人和收件人都不是本系统用户的信件转发。禁止Open Relay是一个最基本的要求,目前大部分邮件服务器都已经关闭了Open Relay功能,但是值得注意的是,某些开源的邮件系统,如Postfix,Qmail默认是允许本机IP(127.0.0.1) Open Relay的,这是一个隐患,因为垃圾邮件已经可以伪造来源IP为127.0.0.1,所以笔者强烈建议调整邮件系统配置,设置本机IP也不允许Open Relay。
4. 对本地用户要求密码认证
对本地用户应该要求密码认证(AUTH LOGIN)以发送邮件,否则垃圾邮件很容易伪造本地用户外发垃圾邮件,从而大大影响了本地用户的声誉,经常会被列入RBL组织的黑名单中。
5. 到各个ESP登记你的IP地址
为了提供你的IP声誉,你还可以主动去各个邮件服务商的网站登记你的IP地址和邮件系统情况,这样将大大减少这些运营商拦截从你的邮件系统发出的邮件的机会。
你可以发送邮件给中国互联网协会反垃圾邮件中心的管理信箱 abuse@anti-spam.cn 登记你的邮件服务器IP和域名的对应关系。
6. 设置SPF记录
SPF是为了防范垃圾邮件而提出来的一种DNS记录类型,它是一种TXT类型的记录,它用于登记某个域名拥有的用来外发邮件的所有IP地址。
dig TXT 21cn.com
21cn.com. 27970 IN TXT "v=spf1 ip4:202.105.45.0/24 ip4:61.140.60.0/24 ip4:202.123.79.206 ip4:220.232.167.218 ip4:221.192.129.0/24 ip4:59.36.102.0/24 -all"
按照SPF的格式在DNS记录中增加一条TXT类型的记录,将提高该域名的信誉度,同时可以防止垃圾邮件伪造该域的发件人发送垃圾邮件。
7. MX设置问题
有一些的比较苛刻的垃圾邮件过滤系统会检查发件人域名的MX记录。首先,MX记录应该设置为有A记录的CNAME。其次,MX记录的刷新时间 (TTL)应该设置不少于7200秒(2小时)。如果,你的邮件服务器的外发IP和接收的IP是不同的,那么最好要求你的接入服务商将外发的IP做一个反向的DNS解释,解释的域名后MX的域名一样。
退 回,被投入接收方的垃圾文件夹甚至被直接丢弃掉(即发送和接收方都没有获得拦截通知)。而一般的企业系统的邮件管理员对反垃圾技术并不是非常了解,所以可 以采取的应对措施不多。以下,我们根据反垃圾技术的特点,列举几项优化邮件系统和操作系统配置的措施,以降低外发邮件被误判的机会。
软件登记工作程序
准备申报材料:
1. 软件登记申请表(单位内部审核存档用,不必提交):
2. 计算机软件著作权登记申请表(中国版权保护中心)
(2份,一份留底,一份,寄版权保护中心)。
(一)软件名称栏:
1.全称:申请著作权登记的软件的全称。按“品牌”+“名称”+“功能或者性质”+“系统”或“软件”或“系统软件”填写;其中的“品牌”可无。例如,新星儿童教育软件。各种文件中的软件名称应填写一致。
2.简称(没有简称不填此栏)。
3.分类号:按照国家标准GB/T13702和GB/4754中的代码确定的分类编号。
4.版本号:申请著作权登记的软件的版本号,按照“V”+“版本号”填写,例如:V1.0。(1)非V1.0版本,如是升级版本,须提交版本升级说明。如是原创性版本,须填写《申请登记软件为原创软件的版本说明》;(2)没有填写版本号,视为V1.0版本。
名称说明:软件用途和技术特点、源程序和文档以及各种相关文件中的软件名称必须和全称或者简称一致。
(二) 开发完成日期栏:
指软件开发者将该软件固定在某种有形物体上的日期。
(三)首次发表日期栏:
指著作权人首次将该软件公之于众的日期。发表是指以赠送、销售、发布和展示等方式向公众提供软件。
单位必须填写本栏。
须在开发完成日同日或者之后。
* 注意:软件的开发完成与首次发表日期均需具体到日。
(四)软件开发情况栏:(根据实际情况选择一项)
1、独立开发:
即单独开发的软件。
2、合作开发:
指由两个以上的自然人、法人或者其他组织合作开发的软件。填此项同时应提交合作开发协议。
3、委托开发:
指委托开发的软件。应提交标明著作权归属的委托开发合同。无委托开发合同的,应提交相关证明。
4、下达任务开发:
指由国家下达任务开发的软件。应提交项目任务书或合同。无项目任务书或合同,应提交相关证明。
(五)原始取得权利栏:
原始取得权利指独立开发软件取得的权利。填写的内容应与上栏提供的证明文件证明的事项一致。选择此栏的,不填写继受取得权利栏。
(六) 继受取得权利栏:
在三种继受的方式中根据实际情况选择(原始取得权利的不填写此栏):
1、继承是指通过继承取得著作权。应提供合法的继承证明,如经过公证的遗嘱或法院判决书等。
2、受让是指经过原著作权人转让取得著作权。应提供明确转让事项的转让合同或法院判决书。
3、承受是指法人或其他组织发生变更和终止,而由其他的法人或其他组织享有软件著作权的情况。申请者应提供合法的承受证明,如工商变更登记证明和法院判决书等。
(七)著作权人:名称(姓名)、国籍和住址
1、名称(姓名):填写公司及其它所有合作单位的名称(不要填写个人的姓名)
2、国籍:中国
3、住址:营业执照副本上的注册地址。
4、提交营业执照副本复印件。
(八)权利范围栏:选择全部。
(九)软件用途和技术特点栏:
1、对软件适用的行业和用途
2、软件的创作目的、主要功能和技术特点。
2、该软件的编程语言及其版本号(★提醒大家在填写软件登记表时注意写明编程语言的具体种类和版本号。)
3、登记软件的开发和运行的硬件环境(机型及CPU)、软件环境(操作系统、支持软件的名称及版本号);
4、源程序量(行数)
5、登记软件的零售价或者报价(必须填写,只是参考价格,不会作为以后著作权人销售定价的依据)。
(十)申请者栏:
如为合作开发,此栏名称栏填写一个单位作为代表即可。
身份证件号栏应填写企业法人登记号,同时加注联系人的姓名、电话。应提交企业法人登记证书的复印件(须加盖公章)。
(十一)代理者栏: (不填写)
(十二)软件鉴别材料交存方式栏:
鉴别材料是指软件程序和文档。注意选择“一般交存”,选择一般交存不再填写本栏其他内容。
一般交存:提交源程序和任何一种文档前后各连续30页。整个程序和文档不到60页的,应当提交整个源程序和文档。程序每页不少于50行,文档每页不少于30行(有图片可例外)。页码为前30页(编为1-30页),后30页(编为31-60页)。
(十三)申请人保证声明栏:
申请人应认真核对申请表格各项内容、应提交的证明文件和鉴别材料是否真实,符合申请要求;明确因提交不真实的申请文件所带来的法律后果。核实无误后,个人申请者签名或者加盖名章;法人或其他组织申请者,由单位加盖公章。签章应为原件,不得为复印件。
3. 说明文档
(2份,一份集团留底,一份,寄版权保护中心)提交纸版和电子版。
如:用户手册,操作手册,设计说明书,使用说明书等,其中任选一项作为文档。
注意:
(1)按文档前30页、后30页提交。第1页为起始页,第60页为结束页。不足60页的需要提交全部文档。 每页不少于30行(页中有插图或结束页可少于30行),第60页为结束页。在每页的右上角标注连续页号1-60。
(2) 文档中出现的日期必须是在申请单位成立之后、软件完成之前这段期间内;文档中出现的公司名称(或个人名字)和软件名称必须通软件著作权登记申请表上填写的 公司名称(或个人名字)和软件名称或简称保持完全一致。(类似错误最容易出现在文档中的软件程序界面图片中)。建议:文档中均不要出现任何人或者任何单位 的名称,标明引用也不允许。
(3)文档中出现图片,须提供合法使用图片的证明材料。
(4)文档中的名称须与申请表中全称或简称一致。
4. 源代码
(1份,寄版权保护中心)提交纸版和电子版。
提醒注意:
① 提交源代码必须使用A4纸,单面打印,并在右上角标注页码(第1页为起始页)。按前、后各连续30页提交,共60页。整个源程序超过60页的,第30和第 31页不能连续,第60页必须为模块结束页。整个源程序不足60页的需要提交全部源程序。除结束页外,每页打印的源代码不得少于50行(空格不计行),在 每页的右上角标注连续页号1-60。可另加封面。
②源代码中出现的公司名称(或个人名字)、软件名称和版本号必须通软件著作权登记申请表上填写的 公司名称(或个人名字)、软件名称和版本号保持完全一致。提交的源代码中不得出现除申请登记的软件著作权人以外的任何个人或单位的名称。建议:提交的源代 码中尽量不要出现任何个人或单位的名称。(类似错误最容易出现在源代码的 @author… @copyright… 中,请注意。)。源程序和文档中均不要出现任何人或者任何单位的名称,标明引用也不允许。
③ 源代码中出现的日期必须是在申请单位成立之后、软件完成之前这段期间内。建议:提交的源代码中尽量不要出现日期。(类似错误最容易出现在源代码的 @date…中,请注意。)
5. 合作、委托开发协议或任务书
(如一次申报n个软件登记,可将其写到一个协议文件中,但需提供n+2份——n:一次同时申请的软件登记数量。)提交纸版和电子版,需盖合同章)
。
申请者如果存在以下情况,要选择提交下面文件:
1)、 合作开发软件 – 提交合同书或协议书复印件(协议各方须盖合同章)
注:需要享受增值税政策的,不要按合作开发软件申报,权利人只填写享受政策的单位名称。
2)、 委托开发软件 — 委托开发合同书或协议书复印件(须加盖公章)
3)、 下达任务开发软件 — 下达任务书复印件(须加盖公章)
6. 企业营业执照
(如一次申报n个软件登记,需提供n+1份复印件——n:一次同时申请的软件登记数量。)1份,寄版权保护中心)提交复印件
注:对于合作开发软件, 须提交各协议各方的公司的营业执照复印件,每个软件一套。
7. 原创软件的版本说明(2.0版本以上的需要)
(2份,一份集团留底,一份寄版权保护中心)提交纸版和电子版,需盖章。
(申请登记软件为原创软件的、高于2.0版本的需要)
8. 用户手册(2.0版本以上的需要)
(2份,一份集团留底,一份,寄版权保护中心)提交纸版和电子版。
9. 不遵守GPL自由软件协议的声明(基于Linux平台开发的需要)
(2份,一份集团留底,一份寄版权保护中心)提交纸版和电子版,需盖章。
若申请软件是基于Linux平台开发的,需提交一份不遵守GPL自由软件协议的声明:说明未修改LINUX内核、未使用开源软件、不遵循GPL协议。
10. 其他材料:
(2份,一份留底,一份寄版权保护中心),提交复印件。
继承取得软件——提交遗嘱证明或者法院相关判决。
转让取得软件协议及董事会或股东会决议——提交转让协议及董事会或股东会决议。
承受取得——提交承受取得证明,如工商证明。
二、邮寄材料
将上述材料除第1条之外的文档寄往如下地址(一个软件一信封,单独邮寄):
邮政编码:100044
北京车公庄大街甲4号物华大厦5层
中国版权保护中心
三、交费(电汇)
寄 资料后半个月左右没有修改意见可直接汇款(也可事先电话咨询:总机:010-68003889, 68003887查询室电话是:68003901 68003220 FAX: 68003887-5105)。(受理通知书等接到汇款后才发出),填写汇款申请单,领导签字,报财务。
费用: 300元/个(其中申请费250元/件,证书费50元/件)
目前的汇款账号:
帐户名:中国版权保护中心(中央财政汇缴专户)
帐号: 7112010189800001174
开户银行:中信实业银行北京阜成门支行
文章地址:
http://www.cublog.cn/u/17999/showart.php?id=159057
运行这个程序需要预先设置栈内存和文件描述符上限, 否则运行失败
ulimit -n 16384
ulimit -s 4096
文件名:server.c
编译: gcc server.c -Wall -O2 -pthread -o server
程序源码如下(请自行编辑宏定义SERVER_IP为自己的IP):
/*Linux 2.6 x86_64 only*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <pthread.h>
#define THREAD_MAX 4096
#define LISTEN_MAX 5000
#define SERVER_IP "192.168.1.103"
typedef struct {
char ip4[128];
int port;
int fd;
} LISTEN_INFO;
//服务器参数
static LISTEN_INFO s_listens[LISTEN_MAX];
//线程池参数
static unsigned int s_thread_para[THREAD_MAX][8];//线程参数
static pthread_t s_tid[THREAD_MAX];//线程ID
pthread_mutex_t s_mutex[THREAD_MAX];//线程锁
//私有函数
static int init_thread_pool(void);
static int init_listen4(char *ip4, int port, int max_link);
//线程函数
void * test_server4(unsigned int thread_para[]);
int main(int argc, char *argv[])//客户端驱动
{
//临时变量
int i, j, rc;
int sock_listen; //监听套接字
int sock_cli; //客户端连接
int listen_index;
int epfd;
int nfds;
struct epoll_event ev;
struct epoll_event events[LISTEN_MAX];
socklen_t addrlen; //地址信息长度
struct sockaddr_in addr4; //IPv4地址结构
//线程池初始化
rc = init_thread_pool();
if (0 != rc) exit(-1);
//初始化服务监听
for(i = 0; i < LISTEN_MAX; i++) {
sprintf(s_listens[i].ip4, "%s", SERVER_IP);
s_listens[i].port = 8000 + i;
//创建监听
rc = init_listen4(s_listens[i].ip4, s_listens[i].port, 64);
if (0 > rc) {
fprintf(stderr, "无法创建服务器监听于%s:%drn", s_listens[i].ip4, s_listens[i].port);
exit(-1);
}
s_listens[i].fd = rc;
}
//设置集合
epfd = epoll_create(8192);
for (i = 0; i < LISTEN_MAX; i++) {
//加入epoll事件集合
ev.events = EPOLLIN;
ev.data.u32 = i;//记录listen数组下标
if (epoll_ctl(epfd, EPOLL_CTL_ADD, s_listens[i].fd, &ev) < 0) {
fprintf(stderr, "向epoll集合添加套接字失败(fd =%d)rn", rc);
exit(-1);
}
}
//服务循环
for( ; ; ) {
//等待epoll事件
nfds = epoll_wait(epfd, events, LISTEN_MAX, -1);
//处理epoll事件
for(i = 0; i < nfds; i++) {
//接收客户端连接
listen_index = events[i].data.u32;
sock_listen = s_listens[listen_index].fd;
addrlen = sizeof(struct sockaddr_in);
bzero(&addr4, addrlen);
sock_cli = accept(sock_listen, (struct sockaddr *)&addr4, &addrlen);
if(0 > sock_cli) {
fprintf(stderr, "接收客户端连接失败n");
continue;
}
//查询空闲线程对
for(j = 0; j < THREAD_MAX; j++) {
if (0 == s_thread_para[j][0]) break;
}
if (j >= THREAD_MAX) {
fprintf(stderr, "线程池已满, 连接将被放弃rn");
shutdown(sock_cli, SHUT_RDWR);
close(sock_cli);
continue;
}
//复制有关参数
s_thread_para[j][0] = 1;//设置活动标志为"活动"
s_thread_para[j][1] = sock_cli;//客户端连接
s_thread_para[j][2] = listen_index;//服务索引
//线程解锁
pthread_mutex_unlock(s_mutex + j);
}//end of for(i;;)
}//end of for(;;)
exit(0);
}
static int init_thread_pool(void)
{
int i, rc;
//初始化线程池参数
for(i = 0; i < THREAD_MAX; i++) {
s_thread_para[i][0] = 0;//设置线程占用标志为"空闲"
s_thread_para[i][7] = i;//线程池索引
pthread_mutex_lock(s_mutex + i);//线程锁
}
//创建线程池
for(i = 0; i < THREAD_MAX; i++) {
rc = pthread_create(s_tid + i, 0, (void *)test_server4, (void *)(s_thread_para[i]));
if (0 != rc) {
fprintf(stderr, "线程创建失败n");
return(-1);
}
}
//成功返回
return(0);
}
static int init_listen4(char *ip4, int port, int max_link)
{
//临时变量
int sock_listen4;
struct sockaddr_in addr4;
unsigned int optval;
struct linger optval1;
//初始化数据结构
bzero(&addr4, sizeof(addr4));
inet_pton(AF_INET, ip4, &(addr4.sin_addr));
addr4.sin_family = AF_INET;
addr4.sin_port = htons(port);
//创建SOCKET
sock_listen4 = socket(AF_INET, SOCK_STREAM, 0);
if (0 > sock_listen4) return(-1);
//设置SO_REUSEADDR选项(服务器快速重起)
optval = 0×1;
setsockopt(sock_listen4, SOL_SOCKET, SO_REUSEADDR, &optval, 4);
//设置SO_LINGER选项(防范CLOSE_WAIT挂住所有套接字)
optval1.l_onoff = 1;
optval1.l_linger = 60;
setsockopt(sock_listen4, SOL_SOCKET, SO_LINGER, &optval1, sizeof(struct linger));
if (0 > bind(sock_listen4, (struct sockaddr *)&addr4, sizeof(addr4))) {
close(sock_listen4);
return(-1);
}
if (0 > listen(sock_listen4, max_link)) {
close(sock_listen4);
return(-1);
}
return(sock_listen4);
}
void * test_server4(unsigned int thread_para[])
{
//临时变量
int pool_index; //线程池索引
int sock_cli; //客户端连接
int listen_index; //监听索引
char buff[32768]; //传输缓冲区
char *p;
int i, j, len;
//线程脱离创建者
pthread_detach(pthread_self());
pool_index = thread_para[7];
wait_unlock:
pthread_mutex_lock(s_mutex + pool_index);//等待线程解锁
//线程变量内容复制
sock_cli = thread_para[1];//客户端连接
listen_index = thread_para[2];//监听索引
//接收请求
len = recv(sock_cli, buff, 32768, MSG_NOSIGNAL);
//构造响应
p = buff;
//HTTP头
p += sprintf(p, "HTTP/1.1 200 OKrn");
p += sprintf(p, "Content-Type: text/htmlrn");
p += sprintf(p, "Connection: closedrnrn");
//页面
p += sprintf(p, "<html>rn<head>rn");
p += sprintf(p, "<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">rn");
p += sprintf(p, "</head>rn");
p += sprintf(p, "<body style="background-color: rgb(229, 229, 229);">rn");
p += sprintf(p, "<center>rn");
p += sprintf(p, "<H3>连接状态</H3>rn");
p += sprintf(p, "<p>服务器地址 %s:%d</p>rn", s_listens[listen_index].ip4, s_listens[listen_index].port);
j = 0;
for(i = 0; i < THREAD_MAX; i++) {
if (0 != s_thread_para[i][0]) j++;
}
p += sprintf(p, "<H3>线程池状态</H3>rn");
p += sprintf(p, "<p>线程池总数 %d 活动线程总数 %d</p>rn", THREAD_MAX, j);
p += sprintf(p, "</center></body></html>rn");
len = p – buff;
//发送响应
send(sock_cli, buff, len, MSG_NOSIGNAL);
//释放连接
shutdown(sock_cli, SHUT_RDWR);
close(sock_cli);
//线程任务结束
thread_para[0] = 0;//设置线程占用标志为"空闲"
goto wait_unlock;
pthread_exit(NULL);
}
1万个监测任务(相当于主机),自动运行100个线程,几秒钟就完成了。
不过并发写数据库日志时,MySQL数据库成为了瓶颈。
现在的架构是: 多进程+多线程的模式工作。
每次监测任务,派生一个子进程;每个子进程根据要监测的任务来自动计算,创建足够的线程来执行具体的监测任务。
最新评论