多层结构scktsrvr的问题 ( 积分: 100 )

  • 主题发起人 主题发起人 itluo
  • 开始时间 开始时间
I

itluo

Unregistered / Unconfirmed
GUEST, unregistred user!
WINDOWS2000/XP,当用超级用户进入WIN,客户端退出时 scktsrvr.exe能正常退出;
当用普通用户登陆WIN,客户端退出时 scktsrvr.exe不能正常关闭 出现failed to create key 211的错误,请大虾们帮帮忙!
 
WINDOWS2000/XP,当用超级用户进入WIN,客户端退出时 scktsrvr.exe能正常退出;
当用普通用户登陆WIN,客户端退出时 scktsrvr.exe不能正常关闭 出现failed to create key 211的错误,请大虾们帮帮忙!
 
DCOM配置
如果在Windows NT环境下正常运行应用服务器,必须进行DCOM配置。配置方法如下:
1. 运行NT服务器上的dcomcnfg程序,进行DCOM配置。
2. 进入DCOM的总体默认属性页面,将“在这台计算机上启用分布式COM”打上勾,将默认身份级别改为“无”。
3. 进入DCOM的总体默认安全机制页面,确认默认访问权限和默认启动权限中的默认值无EveryOne,如果不去掉EveryOne,应用服务器不能正常启动。
4.在常规页面中,双击你的应用服务器,打开你的应用服务器DCOM属性设置。
5.将常规页面中的身份验证级别改为“无”。
6.位置页面中选上“在这台计算机上运行应用程序”。
7.将安全性页面设置中,均选择“使用自定义访问权限”,编辑每一个权限,将EveryOne加入用户列表中。
8.身份标识页面中,选择“交互式用户”。
9.NT的GUEST用户不能禁用。
在google上输入"dcom配置"你可以找到很多。
来自:http://www.delphibbs.com/delphibbs/dispq.asp?lid=877417
一、添加用户
1.在服务器(装有win2000和delphi6.0)上添加用户:administrator,lgf,lxy,lyh
2.在客户机(装win2000或win98均可,无需delphi)上也添加用户:administrator或
lgf或lxy或lyh
切记:服务器和客户机上都要有某用户,若有密码的话,连密码都要一样,否则
会出错的
二、配置服务器端
1.找到在/winnt/system32目录下的文件dcomcnfg.exe,运行之
2.对默认属性作如下设置:
选中"在这台计算机上启动DCOM Intenet 服务";
3.对默认安全机制作如下设置:
a.默认访问权限:编辑默认值,将用户Administrator,lgf,lxy,lyh添加进去,
如果不想逐个指定的话,也可以只添加:Everyone。
b.默认启动权限:编辑默认值,用同样方法将用户Administrator,lgf,lxy,lyh
也添加进去,如果不想逐个指定的话,也可以只添加:Everyone。
好了,大功告成了!现在重启计算机(注销也行),以用户Administrator或lgf
或lxy或lxy登录,切记,只能是上述用户之一!!!
四、生成服务器端程序
1.用delphi编译demos/midas/empedit目录下带的实例:server,生成server.exe
2.用资源管理器找到server.exe,运行一下,即所谓的注册,现在,服务器应用程序
的路径指向:/Borland/Delphi6/Demos/Midas/EmpEdit;如果你将文件server.exe复
制到另一个目录,然后再运行一下,那么,服务器应用程序的路径将指向该目录。
所以需要注意的是,不要将服务器端程序随手放在桌面(/Documents and Settings/
Administrator)上,否则当你用lxy或lgf登录时,因为没有权限进入该目录,所以
在本机都运行不了,更别说客户机了。
五、生成客户端程序
1.用delphi编译demos/midas/empedit目录下带的实例:empedit
2.需要注意的地方:ServerName要选正确了;ComputerName选计算机名或ip地址均可
六、运行客户端程序
1.将生成的文件empedit.exe复制到各个客户机
2.重启客户机(注销也行),以用户Administrator或lgf或lxy或lxy登录
3.在客户机运行程序empedit.exe,啊,成功了
4.切记,如果用其它用户名登录,运行程序empedit.exe,一定死翘翘的。
总结:
1.当我们要写第一个midas程序之前,首先在服务器和客户机上添加Administrator,
lgf诸如此类的用户。并且要在服务器端运行/winnt/system32/dcomcnfg.exe配置一
下,(从此以后,你不用再和它打交道了)
2.提醒一下,如果使用win98作为客户端,千万不要忘了将midas.dll复制到客户机
的windows/system目录下(书上这么说的,但我觉得将midas.dll和客户端程序放在
同一目录,会更保险些)。
看防火有没问题
 
先多谢delphi new,
我用的是 socketConnection 连接.应该不用DCOM配置;
scktsrvr.exe只是 用socketConnection 连接时服务端必须运行的 delphi 本身的提供的一个应用服务.
 
以普通用户(即登陆WIN的用户)安装Delphi试试。
 
超级用户已安装了Delphi,且 普通用户没有安装程序的权限,此法行不通,但还是多谢xianguo.
 
你看scktsrvr.exe的代码,它在退出时在注册表中保存端口,窗口位置等信息了.XP下普通用户不能修改注册表,所以出错了.
 
哦,Codemoocow有好的解决方法吗?
 
必须要用普通用户登录?
 
你可以修改其源代码,把这些信息写入一个配置文件中。
 
楼主,可以将scktsrvr.exe中的TSocketDispatcher类抽出来,封装成一个控件,这样就不需要scktsrvr的窗口了,还可以自己定制,何乐而不为?
 
Codemoocow,谢谢,封装成一个控件的思路不错,不知有没有人成功这样做过.
 
其实不难做,代码如下,将其存为.pas文件,在包中安装就可以了.如何使用就不说了:
unit ScktDsph;
Interface
Uses Windows, ScktComp, SConnect, ActiveX, MidConst, Classes,
WinSock, Messages, SysUtils;
Type
TSocketDispatcherThread = Class;
TClientNotify = Procedure(Thread :TSocketDispatcherThread) Of Object;
TSocketDispatcher = Class(TCustomServerSocket)
Private
FInterceptGUID: AnsiString;
FTimeout: Integer;
FOnAddClient, FOnRemoveClient, FOnClientUpdate :TClientNotify;
Procedure GetThread(Sender :TObject;
ClientSocket :TServerClientWinSocket;
Var SocketThread: TServerClientThread);
Procedure AddClient(Thread :TSocketDispatcherThread);
Procedure RemoveClient(Thread :TSocketDispatcherThread);
Procedure ClientUpdate(Thread :TSocketDispatcherThread);
Public
Constructor Create(AOwner: TComponent);
Override;
Destructor Destroy;
Override;
Public
Property Socket: TServerWinSocket read FServerSocket;
Published
Property InterceptGUID: AnsiString Read FInterceptGUID Write FInterceptGUID;
Property Timeout: Integer Read FTimeout Write FTimeout;
Property OnAddClient :TClientNotify Read FOnAddClient Write FOnAddClient;
Property OnRemoveClient :TClientNotify Read FOnRemoveClient Write FOnRemoveClient;
Property OnClientUpdate :TClientNotify Read FOnClientUpdate Write FOnClientUpdate;

{ TCustomServerSocket }
Property Active;
Property Port Default 211;
Property ThreadCacheSize Default 10;
{
Property ServerType;
Property Service;
Property OnListen;
Property OnAccept;
Property OnGetThread;
Property OnGetSocket;
Property OnThreadStart;
Property OnThreadend;
Property OnClientConnect;
Property OnClientDisconnect;
Property OnClientRead;
Property OnClientWrite;
Property OnClientError;
}
end;
//---------------------------------------------------------------------------
TSocketDispatcherThread = class(TServerClientThread, ISendDataBlock)
private
FRefCount: Integer;
FInterpreter: TDataBlockInterpreter;
FTransport: ITransport;
FInterceptGUID: string;
FLastActivity: TDateTime;
FTimeout: Integer;
FRegisteredOnly: Boolean;
FOnAddClient, FOnRemoveClient, FOnClientUpdate :TClientNotify;
Procedure AddClient;
Procedure RemoveClient;
Procedure ClientUpdate;
protected
function CreateServerTransport: ITransport;
virtual;
{ IUnknown }
function QueryInterface(const IID: TGUID;
out Obj): HResult;
stdcall;
function _AddRef: Integer;
stdcall;
function _Release: Integer;
stdcall;
{ ISendDataBlock }
function Send(const Data: IDataBlock;
WaitForResult: Boolean): IDataBlock;
stdcall;
Public
Constructor Create(CreateSuspended: Boolean;
ASocket: TServerClientWinSocket;
const InterceptGUID: string;
Timeout: Integer;
RegisteredOnly: Boolean);
Procedure ClientExecute;
override;
Public
OwnerData :Pointer;
// provider a Tag for save custom data
Property LastActivity: TDateTime read FLastActivity;
end;

Resourcestring
SNoWinSock2 = '运行程序需要 WinSock 2.0以上版本';
procedure Register;
Implementation
{ TSocketDispatcher }
Constructor TSocketDispatcher.Create(AOwner: TComponent);
begin
If Not LoadWinSock2 then
Raise Exception.CreateRes(@SNoWinSock2);
FServerSocket := TServerWinSocket.Create(INVALID_SOCKET);
InitSocket(FServerSocket);
FServerSocket.ThreadCacheSize := 10;
Port := 211;
ServerType := stThreadBlocking;
OnGetThread := GetThread;
FOnAddClient := Nil;
FOnRemoveClient := Nil;
Inherited Create(AOwner);
end;

Destructor TSocketDispatcher.Destroy;
begin
Inherited Destroy;
end;

procedure TSocketDispatcher.GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
Var SocketThread: TServerClientThread);
begin
SocketThread := TSocketDispatcherThread.Create(False, ClientSocket,
InterceptGUID, Timeout, False);
TSocketDispatcherThread(SocketThread).FOnAddClient := AddClient;
TSocketDispatcherThread(SocketThread).FOnRemoveClient := RemoveClient;
TSocketDispatcherThread(SocketThread).FOnClientUpdate := ClientUpdate;
end;

Procedure TSocketDispatcher.AddClient(Thread :TSocketDispatcherThread);
begin
If Assigned(FOnAddClient) And Not (csLoading In ComponentState) then
FOnAddClient( Thread );
end;

Procedure TSocketDispatcher.RemoveClient( Thread :TSocketDispatcherThread );
begin
If Assigned(FOnRemoveClient) And Not (csLoading In ComponentState) then
FOnRemoveClient(Thread);
end;

Procedure TSocketDispatcher.ClientUpdate(Thread :TSocketDispatcherThread);
begin
If Assigned(FOnClientUpdate) And Not (csLoading In ComponentState) then
FOnClientUpdate(Thread);
end;

{ TSocketDispatcherThread }
constructor TSocketDispatcherThread.Create(CreateSuspended: Boolean;
ASocket: TServerClientWinSocket;
const InterceptGUID: string;
Timeout: Integer;
RegisteredOnly: Boolean);
begin
FInterceptGUID := InterceptGUID;
FTimeout := Timeout;
FLastActivity := Now;
FRegisteredOnly := RegisteredOnly;
OwnerData := Nil;
Inherited Create(CreateSuspended, ASocket);
end;

function TSocketDispatcherThread.CreateServerTransport: ITransport;
var
SocketTransport: TSocketTransport;
begin
SocketTransport := TSocketTransport.Create;
SocketTransport.Socket := ClientSocket;
SocketTransport.InterceptGUID := FInterceptGUID;
Result := SocketTransport as ITransport;
end;

{ TSocketDispatcherThread.IUnknown }
function TSocketDispatcherThread.QueryInterface(const IID: TGUID;
out Obj): HResult;
begin
If GetInterface(IID, Obj) then
Result := 0 else
Result := E_NOINTERFACE;
end;

function TSocketDispatcherThread._AddRef: Integer;
begin
Inc(FRefCount);
Result := FRefCount;
end;

function TSocketDispatcherThread._Release: Integer;
begin
Dec(FRefCount);
Result := FRefCount;
end;

{ TSocketDispatcherThread.ISendDataBlock }
function TSocketDispatcherThread.Send(const Data: IDataBlock;
WaitForResult: Boolean): IDataBlock;
begin
FTransport.Send(Data);
If WaitForResult then
While Truedo
begin
Result := FTransport.Receive(True, 0);
If Result = Nil then
Break;
If (Result.Signature And ResultSig) = ResultSig then
Break
else
FInterpreter.InterpretData(Result);
end;
end;

Procedure TSocketDispatcherThread.ClientExecute;
Var
Data: IDataBlock;
Obj: ISendDataBlock;
Event: THandle;
TimeSub :TDateTime;
Hour, Min, Sec, MSec:Word;
begin
Synchronize(AddClient);
CoInitialize(Nil);
Try
FTransport := CreateServerTransport;
Try
Event := FTransport.GetWaitEvent;
GetInterface(ISendDataBlock, Obj);
If FRegisteredOnly then
FInterpreter := TDataBlockInterpreter.Create(Obj, SSockets)
else
FInterpreter := TDataBlockInterpreter.Create(Obj, '');
Try
Obj := Nil;
While Not Terminated And FTransport.Connecteddo
Try
Case WaitForSingleObject(Event, 60000) Of
// always wait for 1mins for a circle check
WAIT_TIMEOUT:
begin
If (FTimeout = 0) Or (FTransport.Connected = False) then
Continue;
TimeSub := Now - FLastActivity;
DecodeTime(TimeSub, Hour, Min, Sec, MSec);
If Hour*60+Min > FTimeout then
FTransport.Connected := False;
end;

WAIT_OBJECT_0:
begin
WSAResetEvent(Event);
Data := FTransport.Receive(False, 0);
If Assigned(Data) then
begin
FLastActivity := Now;
FInterpreter.InterpretData(Data);
Data := Nil;
FLastActivity := Now;
Synchronize(ClientUpdate);
// try notify socket dispatcher we are updated
end;
end;
end;
Except
FTransport.Connected := False;
end;
Finally
FInterpreter.Free;
FInterpreter := nil;
end;
Finally
FTransport := nil;
end;
Finally
CoUninitialize;
Synchronize(RemoveClient);
end;
end;

Procedure TSocketDispatcherThread.AddClient;
begin
Try
FOnAddClient(Self);
Except
end;
end;

Procedure TSocketDispatcherThread.RemoveClient;
begin
Try
FOnRemoveClient(Self);
Except
end;
end;

Procedure TSocketDispatcherThread.ClientUpdate;
begin
Try
FOnClientUpdate(Self);
Except
end;
end;

procedure Register;
begin
RegisterComponents('DataSnap', [TSocketDispatcher]);
end;

end.
 
佩服得五体投地,此方法应该能解决我的问题,并从中学得不少东西,谢谢Codemoocow.
 
过讲,那些代码都是Borland的,没有一句是我写的.
 
后退
顶部