Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1087004
  • 博文数量: 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:30:32

{线程池报警通信TCP服务器侦听线程,负责接收报警终端的tcp}
TAlarmTCPServer = class(TThread)
private
FAlarmPort : Integer; //报警控制侦听端口
FAlarmCompletePort : THandle; //报警控制部分的完成端口
FThreadPool : TThreadPool; //线程池指针
FAlarmSocketLists : TThreadList; //报警控制Socket数据对象列表
FServerSocket : TSocket; //报警控制侦听Socket
FTimeOutCounter : TTimeOutCounter; //心跳计数线程
function PrepareRecv(PHandelData:LPPerHandelData;Block: PBlock = nil): Boolean;
public
procedure Close(); //安全关闭释放线程
constructor Create(AParent:TThreadPool;CompletePort:THandle;AlarmPort:Integer;ASubDataLs:TThreadList;ATimeOutCounter:TTimeOutCounter);
procedure Execute;override;
destructor Destroy;override;
end;



procedure TAlarmTCPServer.Close;
begin
Self.Terminate;
shutdown(FServerSocket,FD_CLOSE);
closesocket(FServerSocket);
WSACleanup();
end;

constructor TAlarmTCPServer.Create(AParent: TThreadPool;CompletePort:THandle;AlarmPort:Integer;ASubDataLs: TThreadList;ATimeOutCounter:TTimeOutCounter);
var
wsaData: TWSADATA ;
Ret:Integer;
begin
FreeOnTerminate := True;
FTimeOutCounter := ATimeOutCounter;
FThreadPool := AParent;
FAlarmCompletePort := CompletePort;
FAlarmPort := AlarmPort;
FAlarmSocketLists := ASubDataLs;
//初始化侦听网络
Ret := WSAStartup($0202, wsaData);
if Ret <> 0 then
begin
FThreadPool.PShowRealMsg(0,'报警TCP服务','初始化网络失败!');
Self.Terminate;
Exit;
end;
inherited Create(False);
end;

destructor TAlarmTCPServer.Destroy;
begin
inherited;
end;

procedure TAlarmTCPServer.Execute;
var
Ret:Integer;
InternetAddr: SOCKADDR_IN;
Accept:TSocket;
PHandleData:LPPerHandelData;
Flags,RecvBytes:DWORD;
TimeOutObject : TCounterObject;
nRecvBuf,nSendBuf:integer;
Block : pBlock;
i:Integer;
begin
//创建TCPServer的侦听Socket
FServerSocket := WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, nil, 0, WSA_FLAG_OVERLAPPED);
if (FServerSocket = INVALID_SOCKET) then
begin
FThreadPool.PShowRealMsg(0,'报警TCP服务','报警TCPSocket创建失败!');
Self.Terminate;
exit;
end;
//绑定侦听地址和端口
InternetAddr.sin_family := AF_INET;
InternetAddr.sin_addr.s_addr := htonl(INADDR_ANY);
InternetAddr.sin_port := htons(FAlarmPort);
if (bind(FServerSocket, InternetAddr, sizeof(InternetAddr)) = SOCKET_ERROR) then
begin
FThreadPool.PShowRealMsg(0,'报警TCP服务','报警TCP绑定地址和侦听端口失败!');
Self.Terminate;
exit;
end;
//启动服务Socket的侦听
if (listen(FServerSocket, 5) = SOCKET_ERROR) then
begin
FThreadPool.PShowRealMsg(0,'报警TCP服务','报警TCP服务器侦听启动失败!');
Self.Terminate;
exit;
end;
FThreadPool.PShowRealMsg(0,'报警TCP服务','报警TCP服务器侦听线程启动成功!');

//接收客户Socket接入,并放入队列
while( not Self.Terminated ) DO
begin
//侦听报警控制端口,接收新客户端Socket的接入
try
Accept := WSAAccept(FServerSocket, nil, nil, nil, 0);
except
end;

if (Accept = SOCKET_ERROR) then
begin
FThreadPool.PShowRealMsg(0,'报警TCP服务','客户端Socket连接失败!');
Continue;
end else begin
FThreadPool.PShowRealMsg(0,'报警TCP服务','客户端【Socket='+ IntToStr(Accept) +'】接入成功,等待验证!');
end;

//创建接入的Socket对应结构体,并与完成端口关联
PHandleData := LPPerHandelData(GlobalAlloc(GPTR, sizeof(PerHandelData)));
if (PHandleData = nil) then
begin
shutdown(Accept,FD_CLOSE);
closesocket(Accept);
Continue;
end;

//与完成端口关联
PHandleData.Socket := Accept;
if (CreateIoCompletionPort(Accept, FAlarmCompletePort, DWORD(PHandleData), 0) = 0) then
begin
shutdown(Accept,FD_CLOSE);
closesocket(Accept);
GlobalFree(DWORD(PHandleData));
Continue;
end;

PHandleData.PItemPt := nil;
PHandleData.PSrcType := CST_LOGINTYPE_SE; //前端设备登录
PHandleData.Socket := Accept;
PHandleData.PSrcName:='NONAMES';
for i:= 0 to 9 do PHandleData.PDstAddrs[i]:='';
for i:= 0 to 9 do PHandleData.PRoutors[0] := 0;
PHandleData.OperType := APP_OPERTYPE_RECV;
PHandleData.PSrcSectionID := 1;
PHandleData.MemoryBuffer := TMemoryBuffer.Create;
PHandleData.RingBuffer := TRingBuffer.Create(4096 * 10);
FAlarmSocketLists.Add(PHandleData); //保存该Socket对象数据到线程安全列表
TimeOutObject := TCounterObject.Create;
TimeOutObject.PerHandelData := PHandleData;
FTimeOutCounter.PAddClientOfCounter(TimeOutObject); //对该客户端增加心跳计数器
Flags := 0;
nRecvBuf := 0;
nSendBuf := 0;
setsockopt(Accept,SOL_SOCKET,SO_RCVBUF,PChar(@nRecvBuf),sizeof(integer));
setsockopt(Accept,SOL_SOCKET,SO_SNDBUF,PChar(@nSendBuf),sizeof(integer));

//创建Socket数据对象与之关联
Block := PHandleData.MemoryBuffer.AllocBlock;
PrepareRecv(PHandleData,Block);
end;
end;

function TAlarmTCPServer.PrepareRecv(PHandelData:LPPerHandelData; Block: PBlock): Boolean;
var
ErrCode: Integer;
Flags, Transfer: Cardinal;
begin
if not Assigned(Block) then
Block := PHandelData.MemoryBuffer.AllocBlock ;
with Block^.Data do
begin
Flags := 0;
OperType := APP_OPERTYPE_RECV;
FillChar(Buffer, SizeOf(Buffer), 0);
FillChar(Overlapped, SizeOf(Overlapped), 0);
wsaBuffer.buf := @Buffer;
wsaBuffer.len := DATABUF_MAXSIZE;
Result := SOCKET_ERROR <> WSARecv(PHandelData.Socket, @wsaBuffer, 1, @Transfer, @Flags, @Overlapped, nil);
if not Result then
begin
ErrCode := WSAGetLastError;
Result := ErrCode = ERROR_IO_PENDING;
if not Result then
begin
Block.Data.IsUse := False;
end;
end;
end;
end;
 
转载:
阅读(1282) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~