当服务器重启时如何应对大量终端的连接?(100分)

  • 主题发起人 主题发起人 xfeiffer
  • 开始时间 开始时间
X

xfeiffer

Unregistered / Unconfirmed
GUEST, unregistred user!
用TIdTCPServer做的服务器,目前最多能保持1700个左右的Socket在线(自己做测试的时候看了最大连接数在1940,然后就再也没有更多的连接连上来了),而且维持了很长时间,现在有个问题,当服务器打了操作系统补丁重启的时候,大量的终端突然之间连接服务器,开始时还是正常的,但是运行了大概5~10分钟之后就出来了Exception,造成服务器很大的麻烦(CreateThread Error:存储空间不足,无法处理此命令。),而且服务器程序会死机,有没有谁知道为什么会出现这个异常呢?大虾们,在线等待解释啊,谢谢了!!!
[blue]服务器端当Server接收到信息时用的多线程处理数据,而且处理连接(OnConnect)和断开(OnDisconnect)的事件也是多线程处理的,每个线程自己独立的数据库连接(线程中创建ADOConnection和ADOQuery来处理数据)。[/blue]



还有,大家有没有谁用过BoundsChecker6.5ForDelphi版本的?为什么我总是安装不上呢?我用的Delphi7,找了很多地方,都没有介绍如何安装到Delphi7的RTL中的。大虾们帮帮忙呀!!!
 
但是运行了大概5~10分钟之后就出来了Exception,造成服务器很大的麻烦(CreateThread Error:存储空间不足,无法处理此命令。),
帮定,我的程序只有80多个连接就偶尔会出现这个问题。希望了解
 
呵呵,资源太浪费了,继续优化
 
是,检查,检查,再检查……
晕………………
知道错在什么地方了……
 
用一个单元文件来检测内存泄漏(网上有介绍的):
1、将CheckMem单元引用到项目文件的第一项。
program ServerBatchGPRS;
uses
[red]CheckMem in 'CheckMem.pas',[/red]
Forms,
Windows,
Main in 'Main.pas' {FormMain};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TFormMain, FormMain);
Application.Run;
end.

2、将CheckMem.pas文件拷贝到项目源文件目录中。
3、编译并运行,当程序执行完毕之后将会在目录中生成产生内存泄漏的记录(不过具体是哪个地方产生的泄漏还得自己去程序里面慢慢找,最好在网上搜一下那些专门的内存泄漏检测工具,比如BoundsChecker[这个我不会用,呵呵,怎么也安装不到Delphi7中]、MemProof[这个我也不会用,不知道怎么结合Delphi的IDE来调试程序,在网上下载的都是所谓的绿色版,根本没有帮助文件的,晕死,那些转发软件的人真垃圾])。

CheckMem.pas
unit CheckMem; //file:Add it to the first line of project uses

interface

procedure SnapCurrMemStatToFile(Filename: string);

implementation

uses
Windows, SysUtils, TypInfo;

const
MaxCount = High(Word);

var
OldMemMgr: TMemoryManager;
ObjList: array[0..MaxCount] of Pointer;
FreeInList: Integer = 0;
GetMemCount: Integer = 0;
FreeMemCount: Integer = 0;
ReallocMemCount: Integer = 0;

procedure AddToList(P: Pointer);
begin
if FreeInList > High(ObjList) then
begin
MessageBox(0, '内存管理监视器指针列表溢出,请增大列表项数!', '内存管理监视器', mb_ok);
Exit;
end;
ObjList[FreeInList] := P;
Inc(FreeInList);
end;

procedure RemoveFromList(P: Pointer);
var
I: Integer;
begin
for I := 0 to FreeInList - 1 do
if ObjList = P then
begin
Dec(FreeInList);
Move(ObjList[I + 1], ObjList, (FreeInList - I) * SizeOf(Pointer));
Exit;
end;
end;

procedure SnapCurrMemStatToFile(Filename: string);
const
FIELD_WIDTH = 20;
var
OutFile: TextFile;
I, CurrFree, BlockSize: Integer;
HeapStatus: THeapStatus;
Item: TObject;
ptd: PTypeData;
ppi: PPropInfo;

procedure Output(Text: string; Value: integer);
begin
Writeln(OutFile, Text: FIELD_WIDTH, Value div 1024, ' KB(', Value, ' Byte)');
end;

begin
AssignFile(OutFile, Filename);
try
if FileExists(Filename) then
begin
Append(OutFile);
Writeln(OutFile);
end
else
Rewrite(OutFile);
CurrFree := FreeInList;
HeapStatus := GetHeapStatus; { 局部堆状态 }
with HeapStatus do
begin
Writeln(OutFile, '===== ', ExtractFileName(ParamStr(0)), ',', DateTimeToStr(Now), ' =====');
Writeln(OutFile);
Output('可用地址空间 : ', TotalAddrSpace);
Output('未提交部分 : ', TotalUncommitted);
Output('已提交部分 : ', TotalCommitted);
Output('空闲部分 : ', TotalFree);
Output('已分配部分 : ', TotalAllocated);
Output('全部小空闲内存块 : ', FreeSmall);
Output('全部大空闲内存块 : ', FreeBig);
Output('其它未用内存块 : ', Unused);
Output('内存管理器消耗 : ', Overhead);
Writeln(OutFile, '地址空间载入 : ': FIELD_WIDTH, TotalAllocated div (TotalAddrSpace div 100), '%');
end;
Writeln(OutFile);
Writeln(OutFile, Format('当前出现 %d 处内存漏洞 :', [GetMemCount - FreeMemCount]));
for I := 0 to CurrFree - 1 do
begin
Write(OutFile, I: 4, ') ', IntToHex(Cardinal(ObjList), 16), ' - ');
BlockSize := PDWORD(DWORD(ObjList) - 4)^;
Write(OutFile, BlockSize: 4, '($' + IntToHex(BlockSize, 4) + ')字节', ' - ');
try
Item := TObject(ObjList);
if PTypeInfo(Item.ClassInfo).Kind <> tkClass then { type info technique }
write(OutFile, '不是对象')
else
begin
ptd := GetTypeData(PTypeInfo(Item.ClassInfo));
ppi := GetPropInfo(PTypeInfo(Item.ClassInfo), 'Name'); { 如果是TComponent }
if ppi <> nil then
begin
write(OutFile, GetStrProp(Item, ppi));
write(OutFile, ' : ');
end
else
write(OutFile, '(未命名): ');
Write(OutFile, Item.ClassName, ' (', ptd.ClassType.InstanceSize,
' 字节) - In ', ptd.UnitName, '.pas');
end
except
on Exception do
write(OutFile, '不是对象');
end;
writeln(OutFile);
end;
finally
CloseFile(OutFile);
end;
end;

function NewGetMem(Size: Integer): Pointer;
begin
Inc(GetMemCount);
Result := OldMemMgr.GetMem(Size);
AddToList(Result);
end;

function NewFreeMem(P: Pointer): Integer;
begin
Inc(FreeMemCount);
Result := OldMemMgr.FreeMem(P);
RemoveFromList(P);
end;

function NewReallocMem(P: Pointer; Size: Integer): Pointer;
begin
Inc(ReallocMemCount);
Result := OldMemMgr.ReallocMem(P, Size);
RemoveFromList(P);
AddToList(Result);
end;

const
NewMemMgr: TMemoryManager = (
GetMem: NewGetMem;
FreeMem: NewFreeMem;
ReallocMem: NewReallocMem);


initialization
GetMemoryManager(OldMemMgr);
SetMemoryManager(NewMemMgr);

finalization
SetMemoryManager(OldMemMgr);
if (GetMemCount - FreeMemCount) <> 0 then
SnapCurrMemStatToFile(ExtractFileDir(ParamStr(0)) + '/CheckMemory.Log');
end.
 
大并发访问的服务,可以采用重叠io或者完成端口模型
用indy10试试,delphi2006有带的,据说性能有改善。。
 
fastmm4可以检查内存泄漏,在DELPHIBOX有下
 
多人接受答案了。
 
后退
顶部