当前位置:主页>仓库管理软件> 列表

TServerSocket he TClientSocke 找用友软件反记账

库存管理软件版1楼: 我在ServerSocket每隔500毫秒就发送一个命令,这个命令是抄取挂在网上的终端的数据,
这些终端都已经设置好了,当ServerSocket启动的时候,他们会自动连接上来

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

这个程序我是写成了一个服务,定时的去抄数据,一般情况下是正常的,但是总是没有规律的会几天死一次,请问还会有什么问题????

2楼: 自己先顶 如用友软件反记账

3楼: 没有人留言吗 ?
郁闷,
自己再顶

4楼: 试试别加 Socket.Close;

5楼: 试试别加 Socket.Close ?
如果不加这个东西,那么我就要向错误地址发命令了

6楼: 问题可能不是出在这里..

可以贴出代码吗?

库存管理软件版7楼: 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[i].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[i].RemoteAddress = _Ammeter.RemoteAddress then
begin
self.ServerSocket.Socket.Connections[i].SendText(getAmeterCmdByCode(_Ammeter.AmmeterAddress)) ;
//_sleep(800);
//self.ServerSocket.Socket.Connections[i].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[i]+''''''''
else
_Str := _Str + '',''''''+tmpList.Strings[i]+'''''''';
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[i]+'''''',''
end
else
begin
_tmpString := _tmpString+''''''''+ self.CodeList.Strings[i]+''''''''
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[i]+'''''',''
end
else
begin
_tmpString := _tmpString+''''''''+ self.CodeList.Strings[i]+''''''''
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[i]+''''''''
else
_Str := _Str + '',''''''+tmpList.Strings[i]+'''''''';
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[i] ;
FieldByName(''TotalEnergyReading'').AsString := self.DataList.Strings[i] ;
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.

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

9楼: 太郁闷了,有没有人顶呀!!!!!!!!!1111111

10楼: 我只知道 TServerSockett稳定性不好,所以用indy,但最近用indy TTCPServer发出它收资料占用的CPU很(client频繁的connect与disconnect,并发小量的数据包)

郁闷死了


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