Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1087158
  • 博文数量: 282
  • 博客积分: 10865
  • 博客等级: 上将
  • 技术积分: 2480
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-12 12:35
文章存档

2017年(1)

2016年(3)

2015年(10)

2014年(12)

2013年(5)

2012年(10)

2011年(29)

2010年(3)

2008年(13)

2007年(92)

2006年(104)

我的朋友

分类: WINDOWS

2008-10-20 09:34:45

{*******************************************************}
{定义重叠IO的结构体和IO池,便于大量收发并行处理}
{*******************************************************}

unit u_iocp;

interface
uses Windows,winsock2,WinSock,Classes,SysUtils,ComCtrls,Contnrs,u_wimp_def,
u_imgComm,u_Share_RingBuffer;

//==============================================================================
// 定义完成端口的重叠IO数据结构
//==============================================================================
const
DATABUF_MAXSIZE = 4096; //包最大长度
BUF_HEADSIZE = 6; //包头长度
MAX_DESTADDR = 10; //最大同时操作客户端数量

Const
APP_OPERTYPE_RECV = 1; //接收操作
APP_OPERTYPE_SEND = 2; //发送操作
APP_OPERTYPE_POST = 3; //Post操作,是一个socket给另一个socket转发但还没有发出的
APP_OPERTYPE_CLOSE = 4; //关闭socket资源

const
APP_NODEICON_CS = 0; //系统根节点图标索引
APP_NODEICON_FE_ONLINE = 1; //节点图标前端设备上线索引
APP_NODEICON_FE_OFFLINE = 2; //节点图标前端设备下线索引
APP_NODEICON_SECTION = 3; //节点图标分区索引
APP_NODEICON_MS_ONLINE = 4; //节点图标监控主机上线索引
APP_NODEICON_MS_OFFLINE = 5; //节点图标监控主机下线索引
APP_NODEICON_RC_ONLINE = 6; //节点图标远程客户端上线索引
APP_NODEICON_RC_OFFLINE = 7; //节点图标远程客户端下线索引

type

PTreeNodeInfo = ^TtreeNodeInfo;
TtreeNodeInfo= packed record
NodeType : Byte; //节点类型
Item : Pointer; //节点信息指针
end;

type
{需要缓冲在完成端口关联的Socket发送列表中的对象}
TSendObject = class
public
SrcSocket : TSocket;
DstSocket : TSocket;
Buf : array[0..DATABUF_MAXSIZE - 1] of Char;
Len : Integer;
end;

const
//工作状态
WK_NONE = 0;
WK_CONNECTED = 1;
WK_RUNNING = 2;
WK_CLOSE = 3;
WK_IMGTRANS = 4;

type
EMemoryBuffer = class(Exception);
TMemoryBuffer = class;

//视频相关定义
LPImgHandleData = ^PerImgHandelData;
PerImgHandelData = packed record
Socket :TSocket;
Logintype:integer; //登录类型 0 = 底层终端 1=上层主机
Source_Addr : string[7];
Dest_Client : TThreadList; //图像接收端地址列表,仅仅前端设备有此项
Img_Client : LPImgHandleData; //图片文件收发客户端
ConnectTime : TDateTime; //当前连接时间
WorkState : Byte; //工作状态
MEDIA_VEDIO_AUDIO:TSP_MEDIA_VEDIO_AUDIO; //音视频参数
MemoryBuffer:TMemoryBuffer; //结构体和内存池
RingBuffer:TRingBuffer; //环形缓冲
isCompletePac:Boolean;
RevBuffer: array [0..DATABUF_MAXSIZE - 1] of Byte;
isCloseFree:Boolean; //是否释放
end;

LPImgIOData = ^TImgIOData;
TImgIOData = packed record
Overlapped : OVERLAPPED; //完成端口的重叠IO结构
WSABuffer : TWSABUF;
OperType : Byte; //上次命令完成的类型 0:接收 1:发送
IsUse: Boolean;
Buffer: array [0..DATABUF_MAXSIZE - 1] of Byte;
end;

PBlock = ^TBlock;
TBlock = packed record //相当于一个PBLOCK开辟的内存块=4096+n个字节
Data: TImgIOData;
IsUse: Boolean;
end;

TMemoryBuffer = class
private
FList: TList;
FLock: TRTLCriticalSection;
function GetCount: Integer;
function GetBlock(const Index: Integer): PBlock;
protected
property Count: Integer read GetCount;
property Blocks[const Index: Integer]: PBlock read GetBlock;
public
constructor Create(); overload;
constructor Create(BlockCount: Integer); overload;
destructor Destroy; override;
function AllocBlock: PBlock;
procedure RemoveBlock(Block: PBlock);
end;

LPPerHandelData = ^PerHandelData;

{完成键需要关联的句柄(CompletKey),由此判断是由哪个Socket关联的数据}
PerHandelData = packed record
Socket: TSocket; //保留接入的客户端socket句柄
OperType : Byte; //上次命令完成的类型 0:接收 1:发送
PDstAlarmCount: Byte; //报警目标地址数量
PDstAddrs:array[0..MAX_DESTADDR] of String[7]; //目标地址列表
PRoutors:array[0..MAX_DESTADDR] of TSocket; //当该链路的报警信息到,转发的目标路由列表,最多定义两个
PItemPt:TTreeNode; //指向原地址树状元素的指针
PSrcSectionID:Integer; //原地址所在分区号
PSrcType : Byte; //原地址接入类型 1:前端登录类型 2:远程用户端登录 3:监控主机登录
PSrcAddr : string[7]; //原设备地址
PSrcName:string[20]; //原地址的名称
MemoryBuffer:TMemoryBuffer; //结构体和内存池
RingBuffer:TRingBuffer; //环形缓冲
end;

{心跳计数类型}
TCounterObject = class
PerHandelData : LPPerHandelData; //设备TCP链路指针
SrcAddr : String[7]; //设备地址
FTimeOut : ShortInt; //已经超时的秒数 <=60 秒
FTimeOutCn : ShortInt; //已经超时的次数 <=3 次
isTimOut : Boolean; //是否已经超时
end;

Const
DEFAULTBLOCKCN = 100;
BlockSize: Word = SizeOf(TBlock);
implementation

constructor TMemoryBuffer.Create();
begin
Create(DEFAULTBLOCKCN);
end;

constructor TMemoryBuffer.Create(BlockCount: Integer);
var
I: Integer;
P: PBlock;
begin
inherited Create;
InitializeCriticalSection(FLock);
FList := TList.Create;
for I := 0 to BlockCount - 1 do
begin
New(P);
FillChar(P^, BlockSize, 0);
FList.Add(P);
end;
end;

destructor TMemoryBuffer.Destroy;
var
I: Integer;
begin
try
EnterCriticalSection(FLock);

for I := FList.Count - 1 downto 0 do
FreeMem(FList[I]);
FList.Free;
finally
LeaveCriticalSection(FLock);
DeleteCriticalSection(FLock);
end;
inherited Destroy;
end;

function TMemoryBuffer.AllocBlock: PBlock;
var
I: Integer;
begin
EnterCriticalSection(FLock);
try
Result := nil;
//FList.Pack;
for I := FList.Count - 1 downto 0 do
begin
Result := FList[I];
if not Result.IsUse then
break;
end;
if not Assigned(Result) or Result.IsUse then
begin
New(Result);
FList.Add(Result);
end;
FillChar(Result^.Data, SizeOf(Result^.Data), 0);
Result^.IsUse := True;
finally
LeaveCriticalSection(FLock);
end;
end;

//回收内存块到内存池中,可以继续使用
procedure TMemoryBuffer.RemoveBlock(Block: PBlock);
begin
EnterCriticalSection(FLock);
try
Block.IsUse := False;
finally
LeaveCriticalSection(FLock);
end;
end;

function TMemoryBuffer.GetCount: Integer;
begin
Result := FList.Count;
end;

function TMemoryBuffer.GetBlock(const Index: Integer): PBlock;
begin
if (Index >= Count) or (Index <= -1) then
raise EMemoryBuffer.CreateFmt('需要不正确', [Index])
else
Result := FList[Index];
end;

end.
 
转载:
阅读(1369) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~