DIOCP之DEMO-登陆验证设计(二)
ECHOServer代码(不考虑粘包的处理):
unit ufrmMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ActnList, diocp_tcp_server, ExtCtrls,
ComCtrls, utils_safeLogger, utils_BufferPool, utils_fileWriter, System.Actions, ComObj;
type
TfrmMain = class(TForm)
edtPort: TEdit;
btnOpen: TButton;
actlstMain: TActionList;
actOpen: TAction;
actStop: TAction;
btnDisconectAll: TButton;
pgcMain: TPageControl;
TabSheet1: TTabSheet;
tsLog: TTabSheet;
mmoLog: TMemo;
pnlMonitor: TPanel;
btnGetWorkerState: TButton;
btnFindContext: TButton;
pnlTop: TPanel;
btnPostWSAClose: TButton;
btnReOpenTest: TButton;
tmrKickOut: TTimer;
tmrTest: TTimer;
tmrInfo: TTimer;
chkLogDetails: TCheckBox;
tsOperator: TTabSheet;
mmoPushData: TMemo;
btnPushToAll: TButton;
actPushToAll: TAction;
btnPoolInfo: TButton;
edtThread: TEdit;
chkEcho: TCheckBox;
chkShowInMemo: TCheckBox;
chkSaveToFile: TCheckBox;
chkUseContextPool: TCheckBox;
chkUseBufferPool: TCheckBox;
mmo1: TMemo;
btn1: TButton;
mmo2: TMemo;
procedure actOpenExecute(Sender: TObject);
procedure actPushToAllExecute(Sender: TObject);
procedure actStopExecute(Sender: TObject);
procedure btnDisconectAllClick(Sender: TObject);
procedure btnFindContextClick(Sender: TObject);
procedure btnGetWorkerStateClick(Sender: TObject);
procedure btnPoolInfoClick(Sender: TObject);
procedure btnPostWSACloseClick(Sender: TObject);
procedure btnReOpenTestClick(Sender: TObject);
procedure chkEchoClick(Sender: TObject);
procedure chkLogDetailsClick(Sender: TObject);
procedure chkSaveToFileClick(Sender: TObject);
procedure chkShowInMemoClick(Sender: TObject);
procedure chkUseBufferPoolClick(Sender: TObject);
procedure tmrInfoTimer(Sender: TObject);
procedure tmrKickOutTimer(Sender: TObject);
procedure tmrTestTimer(Sender: TObject);
procedure btn1Click(Sender: TObject);
private
//iCounter:Integer;
FChkUseBufferPool:Boolean;
FChkEcho:Boolean;
FChkShowInMemo:Boolean;
FChkSaveToFile:Boolean;
FTcpServer: TDiocpTcpServer;
FPool:PBufferPool;
procedure ReadState;
procedure RefreshState;
procedure OnRecvBuffer(pvClientContext:TIocpClientContext; buf:Pointer;
len:cardinal; errCode:Integer);
procedure OnSendBufferCompleted(pvContext: TIocpClientContext; pvBuff: Pointer;
len: Cardinal; pvBufferTag, pvErrorCode: Integer);
procedure OnAccept(pvSocket: THandle; pvAddr: String; pvPort: Integer; var
vAllowAccept: Boolean);
procedure OnDisconnected(pvClientContext: TIocpClientContext);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
{ Public declarations }
end;
var
frmMain: TfrmMain;
LoginGUID:TStringList;
implementation
uses
uFMMonitor, diocp_core_engine, diocp_core_rawWinSocket,StrUtils;
{$R *.dfm}
constructor TfrmMain.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
sfLogger.setAppender(TStringsAppender.Create(mmoLog.Lines));
sfLogger.AppendInMainThread := true;
FTcpServer := TDiocpTcpServer.Create(Self);
FTcpServer.Name := 'iocpSVR';
FTcpServer.OnDataReceived := self.OnRecvBuffer;
FTcpServer.OnContextAccept := OnAccept;
FTcpServer.createDataMonitor;
FTcpServer.OnSendBufferCompleted := OnSendBufferCompleted;
FTcpServer.OnContextDisconnected := OnDisconnected;
FPool := NewBufferPool(FTcpServer.WSARecvBufferSize);
TFMMonitor.createAsChild(pnlMonitor, FTcpServer);
ReadState;
LoginGUID:=TStringList.Create;
end;
destructor TfrmMain.Destroy;
begin
FTcpServer.SafeStop;
FreeBufferPool(FPool);
FTcpServer.Free;
LoginGUID.Free;
inherited Destroy;
end;
procedure TfrmMain.RefreshState;
begin
if FTcpServer.Active then
begin
btnOpen.Action := actStop;
end else
begin
LoginGUID.Clear;
btnOpen.Action := actOpen;
end;
chkUseContextPool.Enabled := not FTcpServer.Active;
edtPort.Enabled := not FTcpServer.Active;
edtThread.Enabled := not FTcpServer.Active;
end;
procedure TfrmMain.actOpenExecute(Sender: TObject);
begin
FTcpServer.WorkerCount := StrToInt(edtThread.Text);
FTcpServer.Port := StrToInt(edtPort.Text);
FTcpServer.OnDataReceived := self.OnRecvBuffer;
FTcpServer.UseObjectPool := chkUseContextPool.Checked;
FTcpServer.Active := true;
RefreshState;
end;
procedure TfrmMain.actPushToAllExecute(Sender: TObject);
var
ansiStr:AnsiString;
var
lvList:TList;
i:Integer;
lvContext:TIocpClientContext;
begin
ansiStr := mmoPushData.Lines.Text;
lvList := TList.Create;
try
FTcpServer.getOnlineContextList(lvList);
for i:=0 to lvList.Count -1 do
begin
lvContext := TIocpClientContext(lvList[i]);
lvContext.PostWSASendRequest(PAnsiChar(ansiStr), Length(ansiStr));
end;
finally
lvList.Free;
end;
end;
procedure TfrmMain.actStopExecute(Sender: TObject);
begin
FTcpServer.DisconnectAll;
FTcpServer.SafeStop;
RefreshState;
end;
procedure TfrmMain.btn1Click(Sender: TObject);
begin
mmo2.Text:=LoginGUID.Text;
end;
procedure TfrmMain.btnDisconectAllClick(Sender: TObject);
begin
FTcpServer.DisConnectAll();
end;
procedure TfrmMain.btnFindContextClick(Sender: TObject);
var
lvList:TList;
i:Integer;
begin
lvList := TList.Create;
try
FTcpServer.getOnlineContextList(lvList);
for i:=0 to lvList.Count -1 do
begin
FTcpServer.findContext(TIocpClientContext(lvList[i]).SocketHandle);
end;
finally
lvList.Free;
end;
end;
procedure TfrmMain.btnGetWorkerStateClick(Sender: TObject);
begin
ShowMessage(FTcpServer.IocpEngine.getWorkerStateInfo(0));
end;
procedure TfrmMain.btnPoolInfoClick(Sender: TObject);
var
s:string;
r:Integer;
begin
if FPool = nil then Exit;
s :=Format('get:%d, put:%d, addRef:%d, releaseRef:%d, size:%d',
[FPool.FGet, FPool.FPut, FPool.FAddRef, FPool.FReleaseRef, FPool.FSize]);
r := CheckBufferBounds(FPool);
s := s + sLineBreak + Format('池中共有:%d个内存块, 可能[%d]个内存块写入越界的情况', [FPool.FSize, r]);
ShowMessage(s);
end;
procedure TfrmMain.btnPostWSACloseClick(Sender: TObject);
var
lvList:TList;
i:Integer;
begin
lvList := TList.Create;
try
FTcpServer.getOnlineContextList(lvList);
for i:=0 to lvList.Count -1 do
begin
TIocpClientContext(lvList[i]).PostWSACloseRequest();
end;
finally
lvList.Free;
end;
end;
procedure TfrmMain.btnReOpenTestClick(Sender: TObject);
begin
FTcpServer.logMessage('DoHeartBeatChcek', 'DEBUG', lgvDebug);
tmrTest.Enabled := not tmrTest.Enabled;
end;
procedure TfrmMain.chkLogDetailsClick(Sender: TObject);
begin
if chkLogDetails.Checked then
begin
FTcpServer.Logger.LogFilter := LogAllLevels;
end else
begin
FTcpServer.Logger.LogFilter := [lgvError]; // 只记录致命错误
end;
end;
procedure TfrmMain.chkEchoClick(Sender: TObject);
begin
ReadState;
end;
procedure TfrmMain.chkSaveToFileClick(Sender: TObject);
begin
ReadState;
end;
procedure TfrmMain.chkShowInMemoClick(Sender: TObject);
begin
ReadState;
end;
procedure TfrmMain.chkUseBufferPoolClick(Sender: TObject);
begin
ReadState;
end;
procedure TfrmMain.OnAccept(pvSocket: THandle; pvAddr: String; pvPort: Integer;
var vAllowAccept: Boolean);
begin
mmo1.Lines.Add(pvAddr+':'+inttostr(pvPort));
// if pvAddr = '127.0.0.1' then
// vAllowAccept := false;
end;
procedure TfrmMain.OnDisconnected(pvClientContext: TIocpClientContext);
begin
if pvClientContext.Data <> nil then
begin
TObject(pvClientContext.Data).Free;
pvClientContext.Data := nil;
end;
end;
procedure TfrmMain.OnRecvBuffer(pvClientContext:TIocpClientContext;
buf:Pointer; len:cardinal; errCode:Integer);
var
j:Integer;
s:AnsiString;
lvBuff:PByte;
lvFileWriter:TSingleFileWriter;
sGUID:string;
PostGUID:string;
begin
if FChkShowInMemo then
begin
sGUID := CreateClassID;
// 如果客户端发送的为字符串,可以用下面代码进行显示
SetLength(s, len);
Move(buf^, s[1], len);
sfLogger.logMessage(s);
if Pos('GUID',s)>0 then
begin
PostGUID:=midstr(s,6,38);
if LoginGUID.IndexOf(PostGUID)<>-1 then
begin
pvClientContext.PostWSASendRequest( PAnsiChar('Success;GUID='+AnsiString(PostGUID)), Length('Success;GUID='+AnsiString(PostGUID)));
//这里可写其它的业务处理代码,就是一次交互数据等,客户端每次与服务器交互时都带上服务器分配的GUID做为身份名牌
end
else
pvClientContext.PostWSASendRequest(PAnsiChar('Eerror'), Length('Eerror'));
end
else
if s='stu=admin&pwd=admin123' then
begin
LoginGUID.Sorted:=True;
LoginGUID.Duplicates := dupIgnore;
LoginGUID.Add(sGUID);
pvClientContext.PostWSASendRequest( PAnsiChar('Success;GUID='+AnsiString(sGUID)), Length('Success;GUID='+AnsiString(sGUID)));
end
else
begin
pvClientContext.PostWSASendRequest(PAnsiChar('Eerror'), Length('Eerror'));
pvClientContext.DoDisconnect;
end;
end;
if FChkEcho then
begin
if FChkUseBufferPool then
begin
lvBuff := GetBuffer(FPool);
Move(buf^, lvBuff^, len);
//
AddRef(lvBuff);
pvClientContext.PostWSASendRequest(lvBuff, len, dtNone, 1);
end else
begin
pvClientContext.PostWSASendRequest(buf, len);
end;
end;
if FChkShowInMemo then
begin
lvFileWriter := TSingleFileWriter(pvClientContext.Data);
if lvFileWriter = nil then
begin
lvFileWriter := TSingleFileWriter.Create;
pvClientContext.Data := lvFileWriter;
lvFileWriter.FilePreFix := Format('RECV_%d', [pvClientContext.SocketHandle]);
lvFileWriter.FilePerSize := 1024 * 1024 * 100;
end;
lvFileWriter.WriteBuffer(buf, len);
end;
end;
procedure TfrmMain.OnSendBufferCompleted(pvContext: TIocpClientContext; pvBuff:
Pointer; len: Cardinal; pvBufferTag, pvErrorCode: Integer);
begin
if pvBufferTag = 1 then
ReleaseRef(pvBuff);
end;
procedure TfrmMain.ReadState;
begin
FChkEcho := chkEcho.Checked;
FChkShowInMemo := chkShowInMemo.Checked;
FChkUseBufferPool := chkUseBufferPool.Checked;
FChkSaveToFile := chkSaveToFile.Checked;
end;
procedure TfrmMain.tmrInfoTimer(Sender: TObject);
begin
self.Caption := Format('DIOCP 测试:%d, %d', [__DebugWSACreateCounter, __DebugWSACloseCounter]);
end;
procedure TfrmMain.tmrKickOutTimer(Sender: TObject);
begin
FTcpServer.KickOut(30000);
end;
procedure TfrmMain.tmrTestTimer(Sender: TObject);
begin
actStop.Execute;
Application.ProcessMessages;
actOpen.Execute;
end;
end.
DIOCP之DEMO-登陆验证设计(二)的更多相关文章
- WDA演练一:用户登陆界面设计(二)
一,登陆界面设计: 1.将系统编号灰显,默认初值 2.密码栏勾选密码显示,这样就不会明文显示在页面上了: Init方法中添加默认值代码: METHOD wddoinit . DATA lo_nd_zh ...
- Java的登陆验证问题
java中的登陆验证问题可以有多种方式进行验证,通过拦截器功能完成,可以通过过滤器功能完成,也可以简单的代码在JSP页面中单独完成,其中都 涉及到一个关键的验证步骤,这个验证原理ASP,PHP,JAV ...
- Shrio登陆验证实例详细解读(转)
摘要:本文采用了Spring+SpringMVC+Mybatis+Shiro+Msql来写了一个登陆验证的实例,下面来看看过程吧!整个工程基于Mavevn来创建,运行环境为JDK1.6+WIN7+to ...
- 【Java EE 学习 70 上】【数据采集系统第二天】【数据加密处理】【登陆验证】【登陆拦截器】【新建调查】【查询调查】
一.数据加密处理 这里使用MD5加密处理,使用java中自带加密工具类MessageDigest. 该类有一个方法digest,该方法输入参数是一个字符串返回值是一个长度为16的字节数组.最关键的是需 ...
- tornado web高级开发项目之抽屉官网的页面登陆验证、form验证、点赞、评论、文章分页处理、发送邮箱验证码、登陆验证码、注册、发布文章、上传图片
本博文将一步步带领你实现抽屉官网的各种功能:包括登陆.注册.发送邮箱验证码.登陆验证码.页面登陆验证.发布文章.上传图片.form验证.点赞.评论.文章分页处理以及基于tornado的后端和ajax的 ...
- 【Java EE 学习 20】【使用过滤器实现登陆验证、权限认证】【观察者模式和监听器(使用监听器实现统计在线IP、登录IP 、踢人功能)】
一.使用过滤器实现登录验证.权限认证 1.创建5张表 /*使用过滤器实现权限过滤功能*/ /**创建数据库*/ DROP DATABASE day20; CREATE DATABASE day20; ...
- Cookie、Session登陆验证相关介绍和用法
一.Cookie和Session 首先.HTTP协议是无状态的:所谓的无状态是指每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应直接影响,也不会直接 ...
- 1_python小程序之实现用户的注册登陆验证功能
python小程序之实现用户的注册登陆验证功能 程序扼要简述: 一.程序流程:1.程序开始2.判断本地文件/数据库是否已存在用户信息,存在则跳转到登陆,否则跳转到注册,注册成功后后跳转到登陆3.判断 ...
- flask之flask-login登陆验证(一)
这个模块能帮助我们做很多事,最常用到的是,登陆验证(验证当前用户是否已经登陆).记住我功能 一 安装 pip install flask-login 二 导入相关模块及对象并初始化 from flas ...
随机推荐
- web移动端input获得光标Fixed定位失效解决方案
移动端业务开发,iOS 下经常会有 fixed 元素和输入框(input 元素)同时存在的情况. 但是 fixed元素在有软键盘唤起的情况下,会出现许多莫名其妙的问题. 这篇文章里就提供一个简单的有输 ...
- 第七课第三节,T语言流程语句(版本5.0)
for语句 for和while语句一样,都是用来做循环操作的,只是他们的使用方法不一样 (注:关键字,for,end) 执行流程图解: 实例代码: for(var i=0;i<20;i++) / ...
- C#项目实例中读取并修改App.config文件
C#项目是指一系列独特的.复杂的并相互关联的活动,这些活动有着一个明确的目标或目的,必须在特定的时间.预算.资源限定内,依据规范完成.项目参数包括项目范围.质量.成本.时间.资源. 1. 向C#项目实 ...
- js中的this指针(三)
当一个函数并非一个对象的忏悔时,它会被当作一个函数来调用. 此时,函数中的 this 指针被绑定到了全局对象. 后果:方法不能利用内部函数来帮助工作,由于 this 被绑定了错误的值,将无法共享该方法 ...
- 转-利用Oracle审计功能来监测试环境的变化
http://blog.csdn.net/luowangjun/article/details/5627102利用Oracle审计功能来监测试环境的变化 做过测试的人都应该会碰到这样的情况:测试发现的 ...
- Windows环境下使用Redis缓存工具的图文详细方法
一.简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合)和zset(有序集合). ...
- linux网络环境下socket套接字编程(UDP文件传输)
今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...
- Win10外包公司——长年承接Win10App外包、Win10通用应用外包
在几天前的WinHEC大会中,微软特意在大会中展示了其对通用应用的称呼规范,现在,适用于Windows通用平台的应用的正式名称为“Windows应用”(Windows apps),简洁明了. 总而言之 ...
- 2.HTML5 标准改变,准备工作
1.HTML5 标准改变: Html5 不是SGML,XML语言,没有有效性检查,是规范,有松散的写法 不许写结束标签:area,base,br,col,hr,img,input,link,sourc ...
- PLSQL转义字符
http://blog.csdn.net/cunxiyuan108/article/details/5800800