三层中如何在客户端快速检测应用程序服务器准备好了?(100分)

  • 主题发起人 主题发起人 张剑波
  • 开始时间 开始时间

张剑波

Unregistered / Unconfirmed
GUEST, unregistred user!
三层中如何在客户端快速检测应用程序服务器准备好了?

SocketConnection连接,可以先PING一下,看开机没有?
然后:
try
SocketConnection.connected:=true
except
showmessage('out');
end;
等待时间太长。
其他连接方式也可以....
有没有好的方法?
 
try
SocketConnection.connected:=true
except
SocketConnection.connected:=false; //等待时间太长。
//加上这句试试
showmessage('out');
end;
 
你的服务器可可以象整个局域网发广播.客户端收听.
 
如果在同一网段可以看看下面的代码!
服务器:
procedure TForm1.Timer2Timer(Sender: TObject);
begin
NMUDP1.SendBuffer(xkeyword,6);
end;
服务器还可以将自己的IP广播出去
要代码我可以给你
客户端可以如下
procedure TForm1.NMUDP1DataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);
begin

flagip:=FromIp;
NMUDP1.ReadBuffer(xkeyword,numberbytes);//监听

end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin
SocketConnection1.Address:=flagip;
if(xkeyword='starip')then
begin
SocketConnection1.Connected:=true;
flagstar:=1;
Timer2.Enabled:=false;
timer3.Enabled:=true;
//判断是否连接'连接成功'
end;
end;
 
不好意思,说实话,上面各位的代码没有一个可以应付得了
在 SocketConnection1.Connected:=true; 时,应用服务器没有开机,客户机长时间等待的问题。
因为在单线程程序中等待一个未开机的应用服务器,只要执行到上一句,主线程就停止响应,
直到SocketConnection的Connected为True或抛出一个异常,大约时间在60秒,因为WinSocket被初始化的超时时间为60秒左右。

用多线程或事件驱动可以解决这个问题。
以下代码完全基于事件驱动机制,定时时间任选。
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ScktComp, StdCtrls, Db, DBClient, MConnect, SConnect, ExtCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
ClientSocket1: TClientSocket;
SocketConnection1: TSocketConnection;
Timer1: TTimer;
procedure FormCreate(Sender: TObject);
procedure ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure SocketConnection1AfterConnect(Sender: TObject);
procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
ClientSocket1.Address := SocketConnection1.Address; //应用服务器IP
ClientSocket1.Port := SocketConnection1.Port; //应用服务器 Socket Server 端口
Timer1.Enabled := False;
Timer1.Interval := 5000; //定时5秒
end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
SocketConnection1.Connected := True; //因为ClientSocket使用了跟SocketConnection一样的地址和端口
//若它连接成功的话,对方肯定开了而且开了 Socket Server程序
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Active := True; //异步Socket不会阻塞主线程的运行
Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
(Sender as TTimer).Enabled := False; //定时时间到,关闭Socket
ClientSocket1.Active := False;
if not SocketConnection1.Connected then
ShowMessage('连接失败超时,时间:'+
IntToStr(Timer1.Interval div 1000)+'秒');
end;

procedure TForm1.SocketConnection1AfterConnect(Sender: TObject);
begin
ShowMessage('成功连接到AppServer');
end;

procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
var msg: String;
begin
case ErrorCode of
10061: msg := '对方没开Socket Server';
10054: msg := '对方没开机'; //Timer1的定时时间大于60秒时才起作用
else msg := '连接失败!';
end;
ErrorCode := 0;
Timer1.Enabled := False;
ShowMessage(msg);
end;

end.
 
楼上你好:
如果只是要在"三层中如何在客户端快速检测应用程序服务器准备好了?"
那我的方法一定可以的.我做了一个局域网中的考试系统,就是这样.
基本思想是,服务器广播自己的ip,客户断在启动的几秒钟监听.如果客户端听到了服务器的
广播的ip,则将客户端的 SocketConnection.connected设置为true;,如果在这个时间内没有
听到,则提示出错对话框.很显然服务器没有启动,客户端是听不到的!而等待时间你是可以设置的.
上面我的代码就是反映了着个思想!
 
楼上你好:
要看清楚题:"三层中如何[red]在客户端[/red]快速检测应用程序服务器准备好了"
象你的写法,有如下限制
1、应用服务器程序要修改配合,而不仅仅是在客户端检测
2、如果应用服务器程序运行多个实例的话,又要面临如何只打开一个UDP控件的问题。
3、想跨过路由器就不行了

我的办法是利用了如果服务器打开SocketSvr,在客户端检测SocketConnection
[red]将要连接的[/red]IP和端口,如果连接得上,说明应用服务器机器运行了。
我的代码有如下限制:
仅限于使用Socket连接。
 
我就写过一个过程去处理这个问题,用原始的winsock api写的,去连接服务器,设置一个
超时,连接上以后发个消息给主窗口,这个时候就可以启动SocketSvr了
 
szf:
你好!
很高兴和你讨论!
1、关于你说的第一点,没有必要去修改服务器,可以用读ip的函数把服务器ip读出来.
把ip字符串的最后一节改为255,广播出去.这个函数在论坛上能找到的。
2、关于你的第二点,在服务器启动时,自己也要监听一下网络中的广播。比如设置一个关键字
如果听到了,表示已经有一个服务器程序在网络中启动了。如没有听到,则再启动服务器。
以上两点,在我的程序中已经解决了。
3、关于第三点,我承认跨网段就不行了。希望高手赐教!
 
你就在服务器中做一个专门测试的对象,
比如就一个函数就行了:
function IsActive:Boolean...
...
Result:=True;
...
行不行?
 
to tianrei:
作为一个应用服务器,它的主要功能是在远程数据模块提供企业逻辑的实现上,
并不[red]仅仅是为了做数据交换[/red]而存在的,所以没有必要搞这么多不相关的东西。
因此我不会在服务器上动手脚搞这么多网络上的东西。
另外,tianrei兄,你的说法有点儿前后矛盾了,前面说要在服务器上增加一个广播IP包的功能,
后面又说服务器不用任何修改,然后又说服务器启动前也要监听一下。除非你能说服我,三层结构
中的应用服务器本身就应该默认有广播IP包和监听IP包的能力。
最后,跨网段的问题很容易解决----把网络上所有的路由器的IP网络广播的网间转发全部打开就行了。
 
To szf:
如果我把网络上所有的路由器的IP网络广播的网间转发全部打开了,会有带来什么不安全的
隐患或者会出现恶性的结果?[?]
 
张剑波的代码:
---------------------------------------------------------------
SocketConnection连接,可以先PING一下,看开机没有?
然后:
代码:
 try
  SocketConnection.connected:=true
 except
  showmessage('out');
 end;
等待时间太长。
其他连接方式也可以....
有没有好的方法?
---------------------------------------------------------------
这样好像不正确吧?用try不能捕捉到Socket错误,只会在超时后触发错误事件,
如果出错的话。而且socket的connected属性是只读的。不知道是不是我理解错了?
 
to YoungSun:
"用try不能捕捉到Socket错误,只会在超时后触发错误事件"我认为是这样的。
“而且socket的connected属性是只读的”,不会吧?
——————————————————
SZF先生的方案是可行的,简单的、有灵气的,

————————————————
特别感谢(12万分的)szf先生,给你开了个300分的贴子,请笑纳。

 
————————————————
特别感谢(12万分的)szf先生,给你开了个300分的贴子,请笑纳。
http://211.101.4.25/delphibbs/dispq.asp?lid=1158919
 
请问COM/DCOM的三层中如何解决些类问题?我再开300分!
 
接受答案了.
 
to all
那我不如这样:
try
SocketConnection.connected:=true;
finally
if SocketConnection.connected:=false then
begin
showmessage('error');
end;
end;
 
后退
顶部