TServerSocket he TClientSocket 的问题!!!!请大家帮忙(50分)

  • 主题发起人 主题发起人 suipianwuda
  • 开始时间 开始时间
S

suipianwuda

Unregistered / Unconfirmed
GUEST, unregistred user!
我在ServerSocket每隔500毫秒就发送一个命令,这个命令是抄取挂在网上的终端的数据,
这些终端都已经设置好了,当ServerSocket启动的时候,他们会自动连接上来

问题就在,我接受数据的事件中,把读到的数据,处理后存入数据库,
在ServerSocket的OnError中 我的写法
Socket.Close;
ErrorCode:= 0 ;
按理这样做就不会有异常发生,

这个程序我是写成了一个服务,定时的去抄数据,一般情况下是正常的,但是总是没有规律的会几天死一次,请问还会有什么问题????
 
自己先顶
 
没有人留言吗 ?
郁闷,
自己再顶
 
试试别加 Socket.Close;
 
试试别加 Socket.Close ?
如果不加这个东西,那么我就要向错误地址发命令了
 
问题可能不是出在这里..

可以贴出代码吗?
 
unit USocketControl;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Controls,
Dialogs, ExtCtrls, ComCtrls, StdCtrls, Buttons, ScktComp,
DB, ADODB,UServer,UHexUtils;

type
//定义一个再抄表得到数据后触发的事件
TSorcketReadData = procedure(_Region ,_Building,_Termial,_Room,_todo,_AmmeterCoding,_AmmeterAddress,_getData,_Multiple,_Data :string) of Object ;
TSocketGetData = procedure(_AmmeterCoding,_getData :string) of Object ;

TPortServer = Class(TComponent)
private
ServerSocket : TServerSocket ;
CodeList ,DataList : TStringList ;

AdoQuery : TAdoQuery ;

_Date : TDateTime ;

//抄到数据后的事件
FSorcketReadData : TSorcketReadData ;
//抄到数据后触发事件返回客户端
FSocketGetData : TSocketGetData ;

procedure iniServerSocket(_Port : integer) ;
procedure iniAdoQuery ;
procedure iniAdoQueryByNoAndType(_No,_Type : string) ;
procedure iniAmmeter;
public
HaveAmmeter : Boolean ;

_sucessCount : integer ;
Port : integer ;
info : string ;
TerminalList : TStringList ;
AmmeterList : TStringList ;
AmmeterErrorList : TStringList ;

constructor Create(AOwner: TComponent;_Port:integer ;theDate : TDateTime);overload;
constructor Create(AOwner: TComponent;_Port:integer ;theDate : TDateTime;_No ,_Type:string);overload ;
destructor destroy ;override ;

function CheckTerminal : Boolean ;
procedure GetItemData(_Ammeter: TAmmeterObj);
procedure refreshAmmeter;
procedure refreshAmmeterByNoType(_No,_Type : string) ;
procedure SaveDatas ;
procedure CloseSocket ;

procedure ServerSocketClientConnect(Sender: TObject; Socket: TCustomWinSocket);
procedure ServerSocketClientError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure ServerSocketClientRead(Sender: TObject; Socket: TCustomWinSocket);

property SorcketReadData : TSorcketReadData read FSorcketReadData write FSorcketReadData ;
property SocketGetData : TSocketGetData read FSocketGetData write FSocketGetData ;
end;
implementation

uses UConst;


{ TPortServer }

function TPortServer.CheckTerminal: Boolean;
begin
if self.TerminalList.Count > 0 then
begin
Result := True ;
end
else
begin
self.info := '没有检测到任何终端';
Result := False ;
end;
end;

procedure TPortServer.CloseSocket;
var
i : integer ;
begin
for i := 0 to self.ServerSocket.Socket.ActiveConnections -1 do
begin
self.ServerSocket.Socket.Connections.Close ;
end;
self.ServerSocket.Close ;
end;

constructor TPortServer.Create(AOwner: TComponent;_Port: integer;theDate : TDateTime);
begin
inherited Create(AOwner);
_Date := theDate ;
Port := _Port ;
ServerSocket := TServerSocket.Create(self) ;
ServerSocket.OnClientConnect := self.ServerSocketClientConnect ;
ServerSocket.OnClientError := self.ServerSocketClientError ;
ServerSocket.OnClientRead := self.ServerSocketClientRead ;

TerminalList := TStringList.Create ;
AmmeterList := TStringList.Create ;
AmmeterErrorList := TStringList.Create ;
CodeList := TStringList.Create ;
DataList := TStringList.Create ;

AdoQuery := TAdoQuery.Create(self) ;

self.iniServerSocket(_Port) ;
self.iniAdoQuery ;
self.iniAmmeter ;
end;

constructor TPortServer.Create(AOwner: TComponent; _Port: integer;
theDate: TDateTime; _No, _Type: string);
begin
inherited Create(AOwner);
_Date := theDate ;
Port := _Port ;
ServerSocket := TServerSocket.Create(self) ;
ServerSocket.OnClientConnect := self.ServerSocketClientConnect ;
ServerSocket.OnClientError := self.ServerSocketClientError ;
ServerSocket.OnClientRead := self.ServerSocketClientRead ;

TerminalList := TStringList.Create ;
AmmeterList := TStringList.Create ;
AmmeterErrorList := TStringList.Create ;
CodeList := TStringList.Create ;
DataList := TStringList.Create ;

AdoQuery := TAdoQuery.Create(self) ;

self.iniServerSocket(_Port) ;
self.iniAdoQueryByNoAndType(_No,_Type) ;
self.iniAmmeter ;
end;

destructor TPortServer.destroy;
begin
self.ServerSocket.Active := False ;
self.ServerSocket.Free ;
self.TerminalList.Free ;
self.AmmeterList.Free ;
self.AmmeterErrorList.Free ;
self.DataList.Free ;
self.CodeList.Free ;

self.AdoQuery.Free ;
inherited;
end;

procedure TPortServer.GetItemData(_Ammeter: TAmmeterObj);
var
i : integer ;
begin
if self.TerminalList.Count > 0 then
begin
Info := '正采集终端'''+_Ammeter.RemoteAddress +'''下电表'''+_Ammeter.AmmeterAddress +'''';

if self.TerminalList.IndexOf(_Ammeter.RemoteAddress)<> -1 then
begin
for i := 0 to self.ServerSocket.Socket.ActiveConnections -1 do
begin
if self.ServerSocket.Socket.Connections.RemoteAddress = _Ammeter.RemoteAddress then
begin
self.ServerSocket.Socket.Connections.SendText(getAmeterCmdByCode(_Ammeter.AmmeterAddress)) ;
//_sleep(800);
//self.ServerSocket.Socket.Connections.SendText(getAmeterCmdByCode(_Ammeter.AmmeterAddress)) ;
Break ;
end;
end;
end ;
end
else
begin
Info := '没有检测到任何终端';
end;
end;

procedure TPortServer.iniAdoQuery;
begin
with self.AdoQuery do
begin
Connection := frm_Server.ADOConnection ;
SQL.Clear ;
SQL.Text := 'Select D.* from '+
'(select B.CommunicationAddress as TerminalAddress, '+
'B.CommunicationPort as TerminalPort,'+
'C.MultipleNo,C.isSucess,E.Multiple,'+
'c.AmmeterCoding,C.CommunicationAddress as AmmeterAddress from TerminalAmmeter as A '+
'left join TerminalAssets as B on A.TerminalCoding=B.TerminalCoding '+
'left join AmmeterAssets as C on A.AmmeterCoding=C.AmmeterCoding '+
'left join Multiple as E on C.MultipleNo=E.MultipleNo '+
') as D where D.isSucess = 1 and D.TerminalPort='+inttostr(Port);
Open ;
self.HaveAmmeter := (RecordCount > 0);
end;
end;

procedure TPortServer.iniAdoQueryByNoAndType(_No, _Type: string);
var
i : integer ;
Info,_Str : string ;
tmpList : TStringList ;
begin
with self.AdoQuery do
begin
Connection := frm_Server.ADOConnection ;
SQL.Clear ;
//江南大学
if _Type = _Root then
begin
SQL.Text := 'select * from view_All '+
' where TerminalPort='+inttostr(Port) ;
Info := '江南大学' ;
end
else
//校区
if _Type = _Region then
begin
SQL.Text := 'select * from view_All '+
' where RegionNo='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '校区编号:'+_No ;
end
else
//建筑物
if _Type = _Building then
begin
SQL.Text := 'select * from view_All '+
' where BuildingNo='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '建筑物编号:'+_No ;
end
else
//终端
if _Type = _Terminal then
begin
SQL.Text := 'select * from view_All '+
' where TerminalCoding='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '终端:'+_No ;
end
{
else
//总表
if _Type = _Ammeter_Sum then
begin
SQL.Text := 'select * from view_All '+
' where ParentAmmeter='''+_No+''' and TerminalPort='+inttostr(Port) ;
end
}
else
//房间
if _Type = _Room then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All '+
' where BuildingNo='''+tmpList.Strings[0]+
''' and Room='''+tmpList.Strings[1]+''' and TerminalPort='+inttostr(Port) ;
Info := '建筑物编号:'+tmpList.Strings[0] +' 房间:'+tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end
else
//电表
if _Type = _Ammeter then
begin
SQL.Text := 'select * from view_All '+
' where AmmeterCoding='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '电表:'+_No ;
end
else
//部门(某些)
if _Type = _Academe then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
for i := 0 to tmpList.Count -1 do
begin
if i=0 then
_Str := ''''+tmpList.Strings+''''
else
_Str := _Str + ','''+tmpList.Strings+'''';
end;
finally
tmpList.Free ;
end;
SQL.Text := 'select * from view_All where AcademeNo in ('+ _Str +') and TerminalPort='+inttostr(Port);
Info := '部门:'+_Str ;
end
else
//子部门
if _Type = _Branch then
begin
SQL.Text := 'select * from view_All where BranchNo = '''+ _No +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+_No ;
end
else
//校区2
if _Type = _Region_2 then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All where BranchNo = '''+ tmpList.Strings[0] +
''' and RegionNo ='''+ tmpList.Strings[1] +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+ tmpList.Strings[0] +' 校区:'+ tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end
else
//建筑物2
if _Type = _Building_2 then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All where BranchNo = '''+ tmpList.Strings[0] +
''' and BuildingNo ='''+ tmpList.Strings[1] +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+ tmpList.Strings[0] +' 建筑物:'+ tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end ;

Open ;
self.HaveAmmeter := (RecordCount > 0);

//显示客户端需要抄表的数量
frm_Server.StatusBar1.Panels[0].Text := Info+ ' 抄表数量:'+inttostr(self.AdoQuery.RecordCount );
frm_Server.Update ;
end;
end;

procedure TPortServer.iniAmmeter;
var
i : integer ;
_Ammeter : TAmmeterObj ;
begin
self.AmmeterList.Clear ;
self.AdoQuery.First ;
for i := 0 to self.AdoQuery.RecordCount -1 do
begin
_Ammeter := TAmmeterObj.Create ;
_Ammeter.RemoteAddress := self.AdoQuery.fieldByName('TerminalAddress').AsString ;
_Ammeter.AmmeterAddress := self.AdoQuery.fieldByName('AmmeterAddress').AsString ;
self.AmmeterList.AddObject(_Ammeter.AmmeterAddress ,_Ammeter) ;
self.AdoQuery.Next ;
end;
end;

procedure TPortServer.iniServerSocket(_Port: integer);
begin
try
self.ServerSocket.Active := False ;
self.ServerSocket.Port := _Port ;
//度线程的抄
self.ServerSocket.ThreadCacheSize := 200 ;
//self.ServerSocket.ServerType := stThreadBlocking ;
self.ServerSocket.Active := True ;
self.info := '端口:'+inttostr(_Port)+'已经打开,开始连接终端';
except
showMessage('端口:'+inttostr(_Port)+'已经打开,不能同时打开2次!');
Abort ;
end;
end;

procedure TPortServer.refreshAmmeter;
var
_tmpString :string;
_Ammeter : TAmmeterObj ;
i : integer ;
begin
for i := 0 to self.CodeList.Count -1 do
begin
if i <> self.CodeList.Count -1 then
begin
_tmpString := _tmpString+''''+ self.CodeList.Strings+''','
end
else
begin
_tmpString := _tmpString+''''+ self.CodeList.Strings+''''
end;
end;
with self.AdoQuery do
begin
Connection := frm_Server.ADOConnection ;
SQL.Clear ;
SQL.Text := 'Select D.* from '+
'(select B.CommunicationAddress as TerminalAddress, '+
'B.CommunicationPort as TerminalPort,'+
'C.MultipleNo,E.Multiple,'+
'c.AmmeterCoding,C.CommunicationAddress as AmmeterAddress from TerminalAmmeter as A '+
'left join TerminalAssets as B on A.TerminalCoding=B.TerminalCoding '+
'left join AmmeterAssets as C on A.AmmeterCoding=C.AmmeterCoding '+
'left join Multiple as E on C.MultipleNo=E.MultipleNo '+
') as D where D.TerminalPort='+inttostr(Port);
if _tmpString <> '' then
SQL.Text := SQL.Text +' and D.AmmeterCoding not in('+_tmpString +')' ;
Open ;

first ;
self.AmmeterErrorList.Clear ;
for i := 0 to recordCount -1 do
begin
_Ammeter := TAmmeterObj.Create ;
_Ammeter.RemoteAddress := self.AdoQuery.fieldByName('TerminalAddress').AsString ;
_Ammeter.AmmeterAddress := self.AdoQuery.fieldByName('AmmeterAddress').AsString ;
self.AmmeterErrorList.AddObject(_Ammeter.AmmeterAddress ,_Ammeter) ;
Next ;
end;
end;
end;

procedure TPortServer.refreshAmmeterByNoType(_No,_Type : string) ;
var
i : integer ;
_tmpString :string;
theAmmeter : TAmmeterObj ;
Info,_Str : string ;
tmpList : TStringList ;
begin
//得到正确的电表地址列表
for i := 0 to self.CodeList.Count -1 do
begin
if i <> self.CodeList.Count -1 then
begin
_tmpString := _tmpString+''''+ self.CodeList.Strings+''','
end
else
begin
_tmpString := _tmpString+''''+ self.CodeList.Strings+''''
end;
end;

with self.AdoQuery do
begin
Connection := frm_Server.ADOConnection ;
SQL.Clear ;
//江南大学
if _Type = _Root then
begin
SQL.Text := 'select * from view_All '+
' where TerminalPort='+inttostr(Port) ;
Info := '江南大学' ;
end
else
//校区
if _Type = _Region then
begin
SQL.Text := 'select * from view_All '+
' where RegionNo='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '校区编号:'+_No ;
end
else
//建筑物
if _Type = _Building then
begin
SQL.Text := 'select * from view_All '+
' where BuildingNo='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '建筑物编号:'+_No ;
end
else
//终端
if _Type = _Terminal then
begin
SQL.Text := 'select * from view_All '+
' where TerminalCoding='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '终端:'+_No ;
end
{
else
//总表
if _Type = _Ammeter_Sum then
begin
SQL.Text := 'select * from view_All '+
' where ParentAmmeter='''+_No+''' and TerminalPort='+inttostr(Port) ;
end
}
else
//房间
if _Type = _Room then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All '+
' where BuildingNo='''+tmpList.Strings[0]+
''' and Room='''+tmpList.Strings[1]+''' and TerminalPort='+inttostr(Port) ;
Info := '建筑物编号:'+tmpList.Strings[0] +' 房间:'+tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end
else
//电表
if _Type = _Ammeter then
begin
SQL.Text := 'select * from view_All '+
' where AmmeterCoding='''+_No+''' and TerminalPort='+inttostr(Port) ;
Info := '电表:'+_No ;
end
else
//部门(某些)
if _Type = _Academe then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
for i := 0 to tmpList.Count -1 do
begin
if i=0 then
_Str := ''''+tmpList.Strings+''''
else
_Str := _Str + ','''+tmpList.Strings+'''';
end;
finally
tmpList.Free ;
end;
SQL.Text := 'select * from view_All where AcademeNo in ('+ _Str +') and TerminalPort='+inttostr(Port);
Info := '部门:'+_Str ;
end
else
//子部门
if _Type = _Branch then
begin
SQL.Text := 'select * from view_All where BranchNo = '''+ _No +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+_No ;
end
else
//校区2
if _Type = _Region_2 then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All where BranchNo = '''+ tmpList.Strings[0] +
''' and RegionNo ='''+ tmpList.Strings[1] +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+ tmpList.Strings[0] +' 校区:'+ tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end
else
//建筑物2
if _Type = _Building_2 then
begin
tmpList := TStringList.Create ;
try
tmpList.CommaText := _No ;
SQL.Text := 'select * from view_All where BranchNo = '''+ tmpList.Strings[0] +
''' and BuildingNo ='''+ tmpList.Strings[1] +''' and TerminalPort='+inttostr(Port);
Info := '子部门:'+ tmpList.Strings[0] +' 建筑物:'+ tmpList.Strings[1] ;
finally
tmpList.Free ;
end;
end ;

if _tmpString <> '' then
SQL.Text := SQL.Text +' and AmmeterCoding not in('+_tmpString +')' ;
Open ;

first ;
self.AmmeterErrorList.Clear ;
for i := 0 to recordCount -1 do
begin
theAmmeter := TAmmeterObj.Create ;
theAmmeter.RemoteAddress := self.AdoQuery.fieldByName('TerminalAddress').AsString ;
theAmmeter.AmmeterAddress := self.AdoQuery.fieldByName('AmmeterAddress').AsString ;
self.AmmeterErrorList.AddObject(theAmmeter.AmmeterAddress ,theAmmeter) ;
Next ;
end;

//显示客户端需要抄表的数量
frm_Server.StatusBar1.Panels[0].Text := Info+ ' 错误表数量:'+inttostr(self.AdoQuery.RecordCount );
frm_Server.Update ;
end;
end;

procedure TPortServer.SaveDatas;
var
i : integer ;
begin
inherited;
with AdoQuery do
begin
Close ;
SQL.Clear ;
SQL.Text := 'Select * from AmmeterDataRecord where 1=2';
Open ;
for i := 0 to self.CodeList.Count - 1 do
begin
Append ;
FieldByName('Operator').AsString := 'Server' ;
FieldByName('ReadingDate').AsDateTime := _Date ;
FieldByName('AmmeterCoding').AsString := self.CodeList.Strings ;
FieldByName('TotalEnergyReading').AsString := self.DataList.Strings ;
Post ;
end;
end;
end;

procedure TPortServer.ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
self.TerminalList.Add( Socket.RemoteAddress ) ;
self.info := '已经连接上'+inttostr(self.TerminalList.Count)+'个终端';
end;

procedure TPortServer.ServerSocketClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Socket.Close ;
ErrorCode := 0 ;
end;

procedure TPortServer.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
AmmeterAddr : string ;
RecStr : string ;
Datas , Multiple : real ;
begin
inherited;
RecStr := Socket.ReceiveText ;
AmmeterAddr := getAmeterCodeByBackByt(RecStr);
Datas := getAmmeterData(RecStr) ;

if Datas <> -1 then
begin
if self.AdoQuery.Locate('AmmeterAddress',AmmeterAddr,[]) then
begin
inc(_sucessCount);
Multiple := self.AdoQuery.fieldByName('Multiple').AsFloat ;
self.CodeList.Add(self.AdoQuery.fieldByName('AmmeterCoding').AsString) ;
self.DataList.Add(FormatFloat('0.00',Datas*Multiple)) ;

if Assigned(FSorcketReadData) then
begin
FSorcketReadData(self.AdoQuery.fieldByName('RegionName').AsString ,
self.AdoQuery.fieldByName('BuildingName').AsString ,
self.AdoQuery.fieldByName('TerminalAddress').AsString ,
self.AdoQuery.fieldByName('Room').AsString ,
self.AdoQuery.fieldByName('todo').AsString ,
self.AdoQuery.fieldByName('AmmeterCoding').AsString ,
self.AdoQuery.fieldByName('AmmeterAddress').AsString ,
FormatFloat('0.00',Datas),
FormatFloat('0.00',Multiple),
FormatFloat('0.00',Datas*Multiple));
end;

if Assigned(FSocketGetData) then
begin
FSocketGetData(self.AdoQuery.fieldByName('AmmeterAddress').AsString,
FormatFloat('0.00',Datas));
end ;
end;
end;
end;

end.
 
procedure TPortServer.CloseSocket;
var
i : integer ;
begin
for i := 0 to self.ServerSocket.Socket.ActiveConnections -1 do
begin
self.ServerSocket.Socket.Connections.Close ;
end;
self.ServerSocket.Close ;
end;
 
太郁闷了,有没有人顶呀!!!!!!!!!1111111
 
我只知道 TServerSockett稳定性不好,所以用indy,但最近用indy TTCPServer发出它收资料占用的CPU很(client频繁的connect与disconnect,并发小量的数据包)

郁闷死了


楼主若有用TSocketServer比较稳定的写时一定告诉我啊,
 
后退
顶部