内容简介:组里的网络测试仪整个框架是用perl+extjs实现的。项目很大,看了好久了解了整体框架结构。perl+extjs的实现主要有以下几个好处:入口程序为业务逻辑代码靠 GuiServer.pm 承载,并返回内容,主要函数如下:
组里的网络测试仪整个框架是用perl+extjs实现的。项目很大,看了好久了解了整体框架结构。perl+extjs的实现主要有以下几个好处:
- 轻量级,web服务端与业务逻辑紧耦合,无需web服务器去承载应用
- 调用外部命令行程序方便
- 采用ajax技术,省去了频繁的页面跳转
- extjs封装了大量的组件,界面效果风格一致,省去了前端页面开发工作
入口程序为 server.pl
, 启动web服务,监听端口,轮训请求,两个主要函数如下:
sub ServerInit
{
my $group = shift;
my $server_sock = undef;
if($group eq "GUI")
{
$server_sock = &guiServerInit($ServerParams->{CONFIG});
GuiServer->removeShm();
}
elsif($group eq "PKTGEN")
{$server_sock = &pktgenInit($ServerParams->{CONFIG});}
elsif($group eq "CLUSTER_TEST")
{$server_sock = &clusterMasterInit($ServerParams->{CONFIG});}
elsif($group eq "ATTACKENGINE")
{$server_sock = AttackEngineServer::init($ServerParams->{CONFIG});}
if( defined($server_sock) )
{$ServerParams->{"$group"}->{"socket"} = $server_sock;}
else
{
printf("Can not setup $group socket at--[%s, %s]\n", __FILE__, __LINE__);
return 0;
}
$ServerParams->{"SELECT"}->add($ServerParams->{"$group"}->{"socket"});
return 1;
}
sub mainLoop
{
my @ready;
my $sock;
my $sel = $ServerParams->{"SELECT"};
my $GUIConnections = $ServerParams->{"GUI"}->{"connections"};
my $PKTGENConnections = $ServerParams->{"PKTGEN"}->{"connections"};
my $ATTACKENGINEConnections = $ServerParams->{"ATTACKENGINE"}->{"connections"};
my $CLUSTERConnections = $ServerParams->{"CLUSTER_TEST"}->{"connections"};
my $STATConnections = $ServerParams->{"PKTGEN"}->{"connections"};
my $tmpSock;
my $tid;
#starts looping
while(1)
{
#select: BLOCK, selection loop may be interrupted by signals.
@ready = $sel->can_read();
foreach my $fh (@ready)
{
if($fh == $ServerParams->{"GUI"}->{"socket"})
{
#accept the connection
$sock = $fh->accept();
#setup buffer for this connection
$GUIConnections->{"$sock"} = {
"buffer" => ""
};
#add this socket into selection loop
$sel->add($sock);
}
#Connection from PKTGEN
elsif($fh == $ServerParams->{"PKTGEN"}->{"socket"})
{
$sock = $fh->accept();
$PKTGENConnections->{"$sock"} = {
"tid" => "-1",
"buffer" => ""
};
$sel->add($sock);
}
elsif($fh == $ServerParams->{"ATTACKENGINE"}->{"socket"})
{
$sock = $fh->accept();
$sel->add($sock);
$ATTACKENGINEConnections->{"$sock"} = {};
}
elsif($fh == $ServerParams->{"CLUSTER_TEST"}->{"socket"})
{
# connection request from cluster master
$sock = $fh->accept();
$sel->add($sock);
$CLUSTERConnections->{"$sock"} = {
status => "CONNECTED",
buffer => "",
'length' => 0,
DFA => "AUTH"
};
}
elsif(&WhichConnection($fh, "GUI")) #for GUI requests
{
if(! &processGUIRequest_keepalive($fh, $GUIConnections))
{
$sel->remove($fh);
close($fh);
delete $GUIConnections->{"$fh"};
}
}
elsif(&WhichConnection($fh, "CLUSTER_TEST"))
{
if(! &processClusterMasterRequest($fh, $CLUSTERConnections))
{
$sel->remove($fh);
close($fh);
}
}
#stat. from pkt-gens
elsif(&WhichConnection($fh, "PKTGEN")) #for PKTGEN running statistics
{
if(! &processPKTGENMsg_keepalive($fh, $PKTGENConnections))
{
$sel->remove($fh);
close($fh);
delete $PKTGENConnections->{"$fh"};
}
}
elsif(&WhichConnection($fh, "ATTACKENGINE"))
{
if(! AttackEngineServer::processAttackEngineResponse($fh, $ATTACKENGINEConnections->{"$fh"}))
{
$sel->remove($fh);
close($fh);
delete $ATTACKENGINEConnections->{"$fh"};
}
}
else
{
#TODO: error
print("Isolated connection!!!!!!!Never should be here. Need debugging.");
#throw this connection away
$sel->remove($fh);
close($fh);
}
}
# can write
}
}
业务逻辑代码靠 GuiServer.pm 承载,并返回内容,主要函数如下:
sub guiServerInit
{
my $config = shift;
$config_defs->{config} = $config;
$config_defs->{path} = $config->{database}->{xmlDatabasePath};
$config_defs->{maxHistory} = $config->{web}->{maxHistory};
$config_defs->{webRoot} = $config->{web}->{webRoot};
$config_defs->{cacheEnabled} = $config->{web}->{cacheEnabled};
$config_defs->{sessionExpires} = $config->{web}->{sessionExpires};
$config_defs->{port} = $config->{web}->{port};
$config_defs->{protocolTemplates} = $config->{msgCompiler}->{protocolTemplates};
$config_defs->{webVersion} = $config->{web}->{version} ? $config->{web}->{version} : "0.1";
$config_defs->{msgCompilerVersion} = $config->{msgCompiler}->{version} ? $config->{msgCompiler}->{version} : "0.1";
$config_defs->{pktgenVersion} = $config->{pktgenVersion}->{version} ? $config->{pktgenVersion}->{version} : "0.1";
$config_defs->{protocolScripts} = $config->{msgCompiler}->{protocolScripts};
$config_defs->{attackScripts} = $config->{msgCompiler}->{attackScripts};
$config_defs->{database} = Database->getDatabaseConnection() or return undef;
$config_defs->{totParser} = ToTParser->new($config_defs->{protocolTemplates}, $config_defs->{protocolScripts});
#$config_defs->{"physicalPortManager"} = PhysicalPortManager->new("$config_defs->{path}/System/physicalPortManagement.config","$config_defs->{path}/System/ui_physicalPortMapping.config");
$config_defs->{"physicalPortManager"} = PhysicalPortManager->new("$config_defs->{path}");
#$config_defs->{"physicalPortManager"} = shared_clone(PhysicalPortManager->new("$config_defs->{path}"));
#$config_defs->{"ManagementIPConfig"} = ManagementIPConfig->new($MANAGEMENTPORT);
$config_defs->{"ManagementIPConfig"} = ManagementIPConfig->new($config_defs->{path});
# set session time
$config_defs->{sessions} = Session->new($config_defs->{sessionExpires});
$config_defs->{preferences} = Preference->new($config_defs->{path});
$config_defs->{packetGenerator}={};
$config_defs->{packetGenerator}->{port} = $config->{packetGenerator}->{port};
$config_defs->{DocGenerator} = $config->{DocGenerator};
$config_defs->{PcapBuffer} = $config->{PcapBuffer};
# printf("INIT GUI LOG FILE: $config->{web}->{logFile}\n");
if($config->{web}->{logFile} ne "")
{
open($config_defs->{GUILOGFILE}, ">$config->{web}->{logFile}") || die "failed to open gui log file!\n";
guiLog("GUI LOG FILE\n");
}
#print(Dumper($config_defs));
return IO::Socket::INET->new(LocalPort=> $config_defs->{port}, Reuse => 1, Listen => SOMAXCONN);
}
sub parseGUIRequest_keepalive
{
my ($sock, $request, $cleanSockFun) = @_;
my ($ret, $params, $file);
while(length($request->{"buffer"}) > 0)
{
if(! defined($request->{"state"}))
{$request->{"state"} = "WAIT_FOR_HEADER";}
if($request->{"state"} eq "WAIT_FOR_HEADER")
{
# whether http header is ready
$ret = index($request->{"buffer"}, "\r\n\r\n");
if($ret <= 0) # negative
{return "MORE_DATA";}
# cut request header
$request->{"header"} = substr($request->{"buffer"}, 0, $ret + 4);
guiLog(Dumper($request->{"header"}));
substr($request->{"buffer"}, 0, $ret + 4) = "";
if($request->{"header"} =~ m/^.*Accept-Language: ([^\r\n]+)\r\n/s)
{
#Accept-Language: zh-CN,zh;q=0.8
@{$request->{languages}} = split(/ *, */, $1);
}
# parse header
$request->{"header"} =~ m/^.*(GET|get|POST|post)\s+(\S+).*/s;
$request->{"method"} = uc($1);
$request->{"uri"} = $2;
$request->{"header"} =~ m/^.*Connection: (\S+)\r\n.*/s;
$request->{"connection"} = $1;
# parse cookie
if($request->{"header"} =~ m/^.*Cookie: ([^\r\n]+)\r\n/s)
{$request->{"cookies"} = $1;}
# check Modifed-Since
if($request->{"header"} =~ m/^.*If-None-Match/s)
{
print("TODO: return 304 not modifed\n");
print(Dumper($request->{header}));
}
$request->{"uri"} =~ /^([^?]+)(\?(.+))?/;
$request->{"path"} = $1;
if($3){
%{$params} = split(/&|=/, $3);
}
foreach my $pp (keys(%{$params}))
{$request->{"params"}->{$pp} = &urlDecode($params->{$pp});}
$request->{"state"} = "HEADER_READY";
}
if($request->{"state"} eq "HEADER_READY")
{
if($request->{"method"} eq "GET")
{$request->{"state"} = "REQUEST_READY";}
else
{
if($request->{"header"} =~ m/^.*Content-Length:\s+(\d+).*/s)
{$request->{"length"} = $1;}
if($request->{"length"} < 0) # wrong http post request, ignore it.
{return "END";}
else
{
if($request->{"path"} =~ /^\/upload\//i || $request->{"path"} =~ /^\/import\//i)
{$request->{"state"} = "FILE_UPLOADING";}
elsif(length($request->{"buffer"}) >= $request->{"length"})
{
$request->{"data"} = substr($request->{"buffer"}, 0, $request->{"length"});
substr($request->{"buffer"}, 0, $request->{"length"}) = "";
$param = {};
%{$params} = split(/&|=/, $request->{"data"});
foreach my $pp (keys(%{$params}))
{
my $tmpParam=&urlDecode($params->{$pp});
$tmpParam =~ s/^\s+|\s+$//g;#remove head and tail backspeace,equal to string trim
$request->{"params"}->{$pp} = $tmpParam;
}
$request->{"state"} = "REQUEST_READY";
}
else
{return "MORE_DATA";}
}
}
}
# http request is ready
if($request->{"state"} eq "REQUEST_READY")
{
#print("\n++++++++++\n".$request->{"path"}."\n+++++++++++\n");
# forward to ajax,
if($request->{"path"} =~ /^\/ajax\//)
{$ret = &ajaxRequest($sock, $request);}
elsif($request->{"path"} =~ /^\/attackQuery\//)
{$ret = &attackQuery($sock, $request);}
elsif($request->{"path"} =~ /^\/testsQuery\//)
{$ret = &testsQueryProc($sock, $request);}
elsif($request->{"path"} =~ /^\/login\//)
{$ret = &loginProc($sock, $request);}
elsif($request->{"path"} =~ /^\/logout\//)
{$ret = &logoutProc($sock, $request);}
elsif($request->{"path"} =~ /^\/session.js$/)
{$ret = &sessionJSProc($sock, $request);}
elsif($request->{"path"} =~ /^\/command\//)
{$ret = &commandProc($sock, $request);}
elsif($request->{"path"} =~ /^\/export\//)
{$ret = &exportProc($sock, $request);}
elsif($request->{"path"} =~ /^\/testReportsDoc\//)
{$ret = &testReportsDocProc($sock, $request, $cleanSockFun);}
elsif($request->{"path"} =~ /^\/monitor\//)
{$ret = &monitorProc($sock, $request);}
elsif($request->{"path"} =~ /^\/util\//)
{$ret = &utilProc($sock, $request);}
elsif($request->{"path"} =~ /^\/exportPcap\//)
{$ret = &exportPcapProc($sock, $request, $cleanSockFun);}
elsif($request->{"path"} =~ /^\/onlineHelp\//)
{$ret = &onlineHelpProc($sock, $request);}
elsif($request->{"path"} =~ /^\/loadresourcefile\//)
{$ret = &loadResourceFileProc($sock, $request);}
elsif($request->{"path"} =~ /^\/license\//)
{$ret = &licenseProc($sock, $request);}
else
{$ret = &staticFileProc($sock, $request);}
if(! defined($ret))
{printf("connection closed!\n"); return undef;}
foreach my $e (keys(%{$request}))
{
if($e eq "state" || $e eq "buffer")
{next;}
delete $request->{$e};
}
# waiting for next round
$request->{"state"} = "WAIT_FOR_HEADER";
}
if($request->{"state"} eq "FILE_UPLOADING")
{
if(&fileUploadProc($sock, $request))
{
foreach my $e (keys(%{$request}))
{
if($e eq "state" || $e eq "buffer")
{next;}
delete $request->{$e};
}
$request->{"state"} = "WAIT_FOR_HEADER";
}
}
if(defined($request->{"connection"})){
if($request->{"connection"} =~ /close/i)
{printf("Connection to be closed!\n"); return "END";}
}
}
return "MORE_DATA";
}
extjs 在前端通过ajax发起请求,与后端进行交互,示例代码如下:
// 左侧导航历史结果列表数据
var historyresultStore = new Ext.data.JsonStore({
// store configs
autoDestroy : true,
storeId : 'historyresultStore',
proxy : {
type : 'ajax',
url : '/loadresultlist/',
reader : {
type : 'json',
root : 'history',
idProperty : 'id'
}
},
fields : ['name', 'time', 'url']
});
// 左侧导航历史结果列表数据的容器
var historychart = Ext.create('Ext.grid.Panel', {
title : '历史结果',
id : 'historychart',
store : Ext.data.StoreManager.lookup('historyresultStore'),
columns : [{
header:'',
xtype:'rownumberer',
align:'center'
},{
text : '名称',
dataIndex : 'name',
align:'center'
},{
text : '时间',
dataIndex : 'time',
align:'center'
}],
width : "100%",
forceFit : true,
listeners : {
'itemcontextmenu' : function(view, record, item, index, e, eOpts) {
// 禁用浏览器的右键相应事件
e.preventDefault();
e.stopEvent();
// var nodename = record.raw.name;
delete_menu.showAt(e.getXY());
}
},
viewConfig : {
listeners : {
scope : this,
itemdblclick : function(view, record, item, index, e) {
var filename = record.data.url;
Ext.Ajax.request({
url : "/getrunlog/",
method : 'get',
params : {
name : filename
},
success : function(response, opts) {
// 清空tabs内容
Ext.getCmp('tabs').removeAll();
if(Ext.getCmp('Onlynavigationpanel')!=undefined){Ext.getCmp('Onlynavigationpanel').destroy();}
var testreport = Ext.create('Mytestreport');
Ext.getCmp('tabs').add(testreport);
Ext.getCmp('tabs').doLayout(true);
Ext.getCmp('testreport').body
.update('<iframe scrolling="auto" frameborder="0" width="100%" height="100%" src="../../testResult/'
+ filename
+ '/index.html"></iframe>');
// runlog.collapse();
testreport.expand();
// Ext.getCmp('runlog').body.update(response["responseText"]);
},
failure : function(response, opts) {
Ext.MessageBox.alert({
title : '提示信息',
msg : "运行日志获取失败!",
buttons : Ext.Msg.OK
});
}
});
}
}
}
});
// console.log(historyresultStore);
historyresultStore.load();
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 利用Helm简化Kubernetes应用部署
- [应用安全]之ActiveMQ漏洞利用方法总结
- 利用obfuscar对.NET应用进行混淆
- 利用React 16.6新特性优化应用性能
- APP漏洞利用组合拳——应用克隆案例分析
- Win10利用应用商店WSReset.exe进行bypassuac
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Effective java 中文版(第2版)
Joshua Bloch / 俞黎敏 / 机械工业出版社 / 2009-1-1 / 52.00元
本书介绍了在Java编程中78条极具实用价值的经验规则,这些经验规则涵盖了大多数开发人员每天所面临的问题的解决方案。通过对Java平台设计专家所使用的技术的全面描述,揭示了应该做什么,不应该做什么才能产生清晰、健壮和高效的代码。 本书中的每条规则都以简短、独立的小文章形式出现,并通过例子代码加以进一步说明。本书内容全面,结构清晰,讲解详细。可作为技术人员的参考用书。一起来看看 《Effective java 中文版(第2版)》 这本书的介绍吧!