200分,Socketconnection封装为DLL的问题,大富翁快帮帮忙,多少分都给 ( 积分: 200 )

  • 主题发起人 主题发起人 zyyjc
  • 开始时间 开始时间
Z

zyyjc

Unregistered / Unconfirmed
GUEST, unregistred user!
现在公司要做一个项目,已经定下来用Socketconnection
当把SocketConnection封装到Dll中遇到一个问题
问题如下:
当客户端正在正常运行时(调用Dll中的Socketconnection),把Scktsrvr服务器强制关闭,此时客户端报“远程强迫关闭了主机”错误,然后客户端退出的时候没有响应
代码调试发现问题如下(部分代码):
DLL部分:
//初始化Socketconnection(运行正常)
function IniSckt(PApplication: THandle;ServerNameOrIP: WideString;
ServerPort: integer): Boolean;
begin
try
Application.Handle := PApplication;
FServerNameOrIP := ServerNameOrIP;
FServerPort := ServerPort;
if not Assigned(Sckt) then
Sckt := TSocketConnection.Create(Application);
Sckt.Host := FServerNameOrIP;
Sckt.Port := FServerPort;
sckt.ServerGUID := '{D6B81A8D-6B7C-47EE-9EF4-2CAB04BDB5DA}';
sckt.open;
Result:=True;
except
Result:=False;
end;
end;

function FreeSckt: Boolean;
stdcall;
begin
Result := False;
try
if assigned(sckt) then
//显示Sckt.connected为True(这里应该为False才对,哪位大富翁能解答)
begin
sckt.connected:=False;
//调试到这里就运行不了了(为什么会停在这呢?)
FreeAndNil(Sckt);
end;
Result := True;
except
end;
end;
EXE部分:
procedure TForm3.FormShow(Sender: TObject);
begin
if not IniSckt(Application.Handle, '127.0.0.1', 10001) then
begin
ShowMessage('连接服务器失败!');
abort;
end;
end
procedure TForm1.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
FreeSckt;(客户端关闭的时候运行到这里就不动了,DLL中的代码见上面)
end;
各位大富翁帮帮忙看看啊,搞了好几天都没有头绪啊,实在是搞不定了,请求帮助。
 
修改SConnect.PAS //D7
procedure TStreamedConnection.InternalClose;
begin
if Assigned(FTransport) then
begin
FTransport.OnTerminate := nil;
FTransport.Terminate;
PostThreadMessage(FTransport.ThreadID, WM_USER, 0, 0);
if Assigned(FTransport.FTransport) then
WaitForSingleObject(FTransport.Handle, 500);//这里
FTransport := nil;
end else
if Assigned(FTransIntf) then
begin
FTransIntf.Connected := False;
FTransIntf := nil;
end;
end;
 
ysai大侠:
按你的方法试了一下,还是不行
 
你确定你修改过的文件被编译了?设下断点试试
 
编译已通过,运行也很正常
就是如果服务器强制断开后,客户端就出现死机的现在,
跟踪得到的结果在我提出是问题里都有说明
 
别沉了,顶一下
 
等........
 
顶下,=高手来
 
徒簡單,用ICS,要麼自己封裝下API SOCKET,自己處理線程消息循環。
 
嘿嘿,不懂了吧,其实是线程同步搞的鬼。。。
我帮你搞定,不要食言哦。。。
跟你说,他用了FTransport.OnTerminate,其实这个事件在Dll中不能用的。。。
dll中能不能拿到exe中的Application对象?
 
兄弟你看这样行不:
function FreeSckt: Boolean;
stdcall;
begin
Result := False;
try
if assigned(sckt) then
begin
sckt.Close;
//修改这里
FreeAndNil(Sckt);
end;
Result := True;
except
end;
end;
 
不过borland的 Scktsrvr服务器根本不能做企业级应用,你可以参考一下:
http://delphibbs.com/delphibbs/dispq.asp?lid=3816911
 
function FreeSckt: Boolean;
stdcall;
begin
Result := False;
try
if assigned(sckt) then
//显示Sckt.connected为True(这里应该为False才对,哪位大富翁能解答)
begin
sckt.connected:=False;
//调试到这里就运行不了了(为什么会停在这呢?)
FreeAndNil(Sckt);
end;
Result := True;
except
end;
end;

记得Sckt.SupportCallbacks:=false 要不退出会不动的 我会这样写:
if sckt<>nil then

sktSpea.Connected:=false;
如果是拉的组件没有必要用freeandNil(sckt)这句了,程序自动会做好的.
 
TO:lake_cx
以为这贴要沉了,看到你的留言,又看到了希望了
我也分析过应该是DLL中的Application的问题,
可是还没找到解决的办法,
你分析的比我详细,不知道能不能解决这个问题呢?
无论如何,都会给分
 
通过这几天对TSocketConnection控件的研究,发现原来它是通过一个叫TTransportThread的线程来连接服务器程序的,就如&quot;lake_cx&quot;所说的DLL存在线程同步的问题,在FTransport.OnTerminat事件中不能释放掉连接,才导致客户端出现死机的现在.可是知道的问题存在的原因了,还是不知道怎么解决,不知道还有没有好心的大富翁同志帮帮忙,开导开导啊.
TO lake_cx大侠:应该要怎么改,能否说说
 
我是这么干的,勉强可以搞定
unit UntSocketPatch;
interface
uses Windows, Classes, Messages, ScktComp, ExtCtrls, Forms, PlatFormAPI;
type
TDllPatch = class(TComponent)
private
FApp: TApplication;
FOnMessage: TMessageEvent;
FOnIdle: TIdleEvent;
proceduredo
Idle(Sender: TObject;
vardo
ne: Boolean);
proceduredo
Message(var Msg: TMsg;
var Handled: Boolean);
public
constructor Create(App: TApplication);
overload;
destructor Destroy;
override;
end;

var
DllPatch: TDllPatch;
implementation
uses SysUtils;
{ TDllPatch }
constructor TDllPatch.Create(App: TApplication);
begin
inherited Create(App);
FApp := App;
FOnMessage := FApp.OnMessage;
FOnIdle := FApp.OnIdle;
FApp.OnMessage :=do
Message;
FApp.OnIdle :=do
Idle;
FApp.HookSynchronizeWakeup;
end;

destructor TDllPatch.Destroy;
begin
if DllPatch = Self then
DllPatch := nil;
FApp.OnMessage := FOnMessage;
FApp.OnIdle := FOnIdle;
inherited;
end;

procedure TDllPatch.DoIdle(Sender: TObject;
vardo
ne: Boolean);
begin
if Assigned(FOnIdle) then
FOnIdle(Sender,do
ne);
if (GetCurrentThreadID = MainThreadID) and CheckSynchronize then
do
ne := False;
end;

procedure TDllPatch.DoMessage(var Msg: TMsg;
var Handled: Boolean);
begin
if Assigned(FOnMessage) then
FOnMessage(Msg, Handled);
if Handled then
Exit;
Handled := True;
case Msg.message of
WM_NULL:
CheckSynchronize;
else
Handled := False;
end;
end;

end.

然后比如说你的这个dll某一个入口函数(最好是在第一次载入dll时调用的函数),有参数Application(主应用程序的)
就调用一下TDllPatch.Create(Application);
看看能不能解决问题
 
感谢lake_cx大侠及各位DFW热情的帮忙
 
后退
顶部