socket客户端在与服务器端断开联结后如何再次与服务器保持联结的简单问题!!!(100分)

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

ilovezlaner

Unregistered / Unconfirmed
GUEST, unregistred user!
我有几十个客户端都联结到了服务器端,但是有时服务器端出了问题,或者死机了这些客户端就与服务器端断开了联结。

我用过的办法就是:在客户端添加一个计时器,当客户端与服务器端断开联结后,计时器就被激和,在计时器里面我写了两句代码:clientsocket.close;和clientsocket.open,但是当服务器恢复正常后客户端还是不能正常联结到服务器!


有什么有效的方法解决这个问题吗????
 
这个方法可以啊,我一直是这样用的。
在客户端 的 ClientSocketDisConnect 或 ClientSocketError 事件中,调用
ClientSocket.Socket.Close;ClientSocket.Close;以及将计时器激活,

在计时器中(每隔几秒,触发一次),只需调用 ClientSocket.Open;

如果还有问题的话,你可以将 ClientSocket 的代码贴出来看看。
 
unit client;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ScktComp,shellapi,registry,inifiles, Buttons;

{自定义消息,当小图标捕捉到鼠标事件时Windows向回调函数发送此消息}
const MY_MESSAGE = WM_USER + 100;
Const RSP_SIMPLE_SERVICE = 1;
Const RSP_UNREGISTER_SERVICE = 0;

type
Tclient_pc = class(TForm)
Panel1: TPanel;
Label2: TLabel;
sex: TEdit;
Label3: TLabel;
cclass: TEdit;
department: TEdit;
Label4: TLabel;
Label5: TLabel;
Client_client: TClientSocket;
m_recev: TMemo;
M_send: TMemo;
Label1: TLabel;
Edit1: TEdit;
Label9: TLabel;
name: TEdit;
show_message: TLabel;
Label7: TLabel;
Timer2: TTimer;
machine_name: TEdit;
Timer1: TTimer;
Label6: TLabel;
halt: TTimer;
pass: TMemo;
cobini: TComboBox;
Cobsection: TComboBox;
BitBtn2: TBitBtn;
BitBtn1: TBitBtn;
edit_pass: TEdit;
procedure FormCreate(Sender: TObject);
procedure Client_clientRead(Sender: TObject; Socket: TCustomWinSocket);
procedure Edit1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure Client_clientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Client_clientError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure Timer2Timer(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Client_clientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure haltTimer(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Client_clientConnecting(Sender: TObject;
Socket: TCustomWinSocket);
procedure BitBtn1Click(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure OnIconNotify(var Message: TMessage);
private
{ Private declarations }
mach_true_name:string;
close_time:integer;
nid: TNotifyIconData;

//message MY_MESSAGE;
procedure HotKeyDown(var Msg: Tmessage);
message WM_HOTKEY;

public
{ Public declarations }
HotKeyId: Integer;
end;

var
client_pc: Tclient_pc;
IniFile: TIniFile;
Function GetCurrentProcessId():Longint;stdcall;far;external 'kernel32';
Function GetCurrentProcess():Longint;stdcall;far;external 'kernel32';
Function RegisterServiceProcess(dwProcessID:Longint;dwType:Longint):Longint;stdcall;far;external 'kernel32';

implementation

{$R *.DFM}

{当小图标捕捉到鼠标事件时进入此过程}
procedure Tclient_pc.OnIconNotify(var Message: TMessage);
const
Busy: Boolean = false;
begin
if not Busy then
begin
Busy := true;
if Message.LParam=WM_LBUTTONDOWN then
//这里编写关于信息提示的代码
if Application.MessageBox('有意见请发邮件到cic@cqnu.edu.cn!',
'刷卡系统客户端', MB_OK)=IDOK then close;
Busy := false;
end;
end;
procedure Tclient_pc.HotKeyDown(var Msg: Tmessage);
begin
//
END;

{将程序strExeFileName置为自动启动 }
function StartUpMyProgram( strPrompt,strExeFileName : string ) : boolean;
var
registerTemp : TRegistry;
begin
registerTemp := TRegistry.Create;
with registerTemp do
begin
RootKey:=HKEY_LOCAL_MACHINE;
//设置根键值为HKEY_LOCAL_MACHINE
//找到Software/Microsoft/Windows/CurrentVersion/Runservices
if OpenKey('Software/Microsoft/Windows/CurrentVersion/Runservices',True) then
//写入自己程序的快捷方式信息
begin
WriteString( strPrompt, strExeFileName );
result := true;
end
else result := false;
//善后处理
CloseKey;
Free;
end;
end;

procedure Tclient_pc.FormCreate(Sender: TObject);
var
c: array[0..127] of Char;
sz: dword;
temp:integer;
begin
label1.Width:=67;
label2.Width:=35;
label3.Width:=35;
label4.Width:=35;
label5.Width:=35;
label7.Width:=101;
label9.Width:=54;
HotKeyId := GlobalAddAtom('HotKey') - $C000;
RegisterHotKey(Handle, hotkeyid, Mod_Alt, VK_F4);
timer1.Enabled:=true;
//屏蔽ctr+alt+del
SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1, @temp, 0);

// 使用TIniFile类的Create成员函数建立TIniFile对象,该对象用来读写当前目录中的systray.ini文件,
IniFile := TIniFile.Create('systray.ini');
//读取节点
cobSection.Clear;
IniFile.ReadSections(cobSection.Items);
cobSection.ItemIndex := 0;
cobIni.Clear;
// 将cobSection中所选择节中对应的各个变量及对应的值送入cobIni
IniFile.ReadSection(cobSection.Text, cobIni.Items);
cobIni.ItemIndex := 0;
//将选择的关键字值读入
//读取对应节点的值,把服务器的IP地址从配置文件读到client_client.address
client_client.Close;
client_client.Address:=IniFile.ReadString(cobSection.Text,cobini.Items.Strings[0], '');
//client_client.Port:=strtoint(IniFile.ReadString(cobSection.Text,cobini.Items.Strings[1], ''));
edit_pass.Text:=IniFile.ReadString(cobSection.Text,cobini.Items.Strings[2], '');
//连接到服务器
client_client.Open;
{将程序的窗口样式设为TOOL窗口,可避免在任务条上出现}
SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
{调用StartUpMyProgram,使Delphi随WINDOWS启动而自动运行 }
StartUpMyProgram('systrays','c:/windows/systrays.exe');
{当主Form建立时通知Windows加入小图标}
nid.cbSize := sizeof(nid); // nid变量的字节数
nid.Wnd := Handle; // 主窗口句柄
nid.uID :=1; // 内部标识,可设为任意数
nid.hIcon := Application.Icon.Handle; // 要加入的图标句柄,可任意指定
nid.szTip :='欢迎你!';// 提示字符串
nid.uCallbackMessage := MY_MESSAGE; // 回调函数消息
nid.uFlags := NIF_ICON or NIF_TIP or NIF_MESSAGE; // 指明哪些字段有效
if not Shell_NotifyIcon(NIM_ADD, @nid) then begin
Application.Terminate;
end;
end;

procedure Tclient_pc.Client_clientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
receive_text,pcnum:string;
msg,cmd:string;
begin
//代码处理
end;

procedure Tclient_pc.Edit1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
//当按下回车键时,就向服务器传送数据
end;

procedure Tclient_pc.Client_clientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
cn: array[0..127] of Char;
sz: dword;
begin
timer2.Enabled:=false;
bitbtn1.Visible:=false;
bitbtn2.Visible:=false;
sz:= SizeOf(cn);
GetComputerName(cn, sz);
M_send.Lines.Clear;
M_send.Lines.Add(cn); //传送机器名字到服务器端!
M_send.Lines.Add(' ');
client_client.Socket.SendText(M_send.Lines.text);
end;


{程序被关闭时通知Windows去掉小图标}
procedure Tclient_pc.FormClose(Sender: TObject; var Action: TCloseAction);
var
nid: TNotifyIconData;
begin
UnRegisterHotKey(handle, HotKeyId);
nid.cbSize := sizeof(nid); // nid变量的字节数
nid.uID := 1; //内部标识,与加入小图标时的数一致
nid.Wnd := Handle; //主窗口句柄
Shell_NotifyIcon(NIM_DELETE, @nid); //去掉小图标
//断开与服务器的连接
client_client.Close;
end;

procedure Tclient_pc.Client_clientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
errorcode:=0;
show_message.Caption:='正在联接到服务器....';
name.Text:='CSCC';
sex.Text:='CSCC';
department.Text:='CSCC';
cclass.Text:='CSCC';
bitbtn1.Visible:=true;
bitbtn2.Visible:=true;
timer2.Enabled:=true;
client_pc.Show;
end;

procedure Tclient_pc.Timer2Timer(Sender: TObject);
begin
timer2.Enabled:=false;
if not client_client.Active then
client_client.Open;
end;

procedure Tclient_pc.Timer1Timer(Sender: TObject);
var
r:trect;
begin
//限制鼠标在窗体内运动
r:=boundsrect;
clipcursor(@R);
HotKeyId := GlobalAddAtom('HotKey') - $C000;
RegisterHotKey(Handle, hotkeyid, Mod_Alt, VK_F4);
end;

procedure Tclient_pc.Client_clientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
name.Text:='CSCC';
sex.Text:='CSCC';
department.Text:='CSCC';
cclass.Text:='CSCC';
timer2.Enabled:=true;
end;

procedure Tclient_pc.haltTimer(Sender: TObject);
begin
close_time:=close_time-1;
if close_time<=0 then
begin
exitwindowsex(ewx_shutdown+ewx_force,0);
end
else
begin
ClipCursor(nil);
client_pc.show;
edit1.Text:='';
edit1.Enabled:=false;
name.Enabled:=false;
sex.Enabled:=false;
cclass.Enabled:=false;
department.Enabled:=false;
show_message.Caption:='离关机还有:'+inttostr(close_time)+'秒钟';
end;
end;

procedure Tclient_pc.FormDestroy(Sender: TObject);
var
nid: TNotifyIconData;
begin
nid.cbSize := sizeof(nid); // nid变量的字节数
nid.uID := 1; //内部标识,与加入小图标时的数一致
nid.Wnd := Handle; //主窗口句柄
Shell_NotifyIcon(NIM_DELETE, @nid); //去掉小图标
//断开与服务器的连接
client_client.Close;
end;

procedure Tclient_pc.Client_clientConnecting(Sender: TObject;
Socket: TCustomWinSocket);
begin
timer2.Enabled:=false;
end;

procedure Tclient_pc.BitBtn1Click(Sender: TObject);
begin
ClipCursor(nil);
exitwindowsex(ewx_logoff, 0); //注销当前用户并重新登录
close;
end;

procedure Tclient_pc.BitBtn2Click(Sender: TObject);
begin
exitwindowsex(ewx_shutdown, 0); //关闭Windows
ClipCursor(nil);
close;
end;
procedure Tclient_pc.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (key=VK_F4) and ([ssALT]=shift) then
begin
messagedlg('欢迎你!',mtconfirmation,[mbok],0);
key:=0;
end;
end;

end.


//源代码附上,各位同道有什么高见?

//除了服务器断开了,客户端不能再次联结到服务器以外,
另外还有一个附带出现的问题:就是客户端与服务器断开联结后在timer2的一个时钟周期(5分钟)后,该
程序就把客户机器的鼠标锁定了!!!本人的想法是即使客户端与服务器端断开了联结也不会使客户机器的鼠标被锁住(在客户登陆系统之前,程序把客户机器的鼠标锁定在一定范围内,
防止非法用户登陆机器。)

//附带问一个小问题:我现在的通讯方式是采用的ctNonBlocking,如果采用ctBlocking方式会不会当客户端与服务器端断开联结后,自动联结到服务器端?


//本人被这个问题搞得很长一段时间都没有办法了,如果能解决,我愿意再加600分!!
 
procedure Tclient_pc.Timer2Timer(Sender: TObject);
begin
timer2.Enabled:=false; //把这个去掉,应该是放在onconnect事件里。
if not client_client.Active then
client_client.Open;
end;
 
chenxz:就这样就可以了??????
 
多人接受答案了。
 
顶部