我用delphi调用一个C语言编写的dll,每次都是第一次执行正常,第二次就出错了。但是同样的调用直接用按钮调用就没事!procedure TPrm_Proxy.IdTCPServer_DB_TuxedoExecute(AThread: TIdPeerThread);
Var
StrRe:String;
StrArrRe:Array [0..19] of String;
StrMobileNumber,StrPwd:String;
Stra,Strb,Strc,Strd:pChar;
IntRe:integer; Handle: THandle;
Auth: TMyApp;
begin
if not AThread.Terminated and AThread.Connection.Connected then //注意这里
begin
StrRe:=AThread.Connection.ReadLn();
MemoDealInfo.Lines.Add('--->'+DateTimeToStr(Now)+':收到来自客户端'+ AThread.Connection.Socket.Binding.PeerIP+':'+inttoStr (AThread.Connection.Socket.Binding.PeerPort)+'的请求信息:'+StrRe); //拆分客户端传来的(日志、Tuxedo请求)信息A|B|C
SplitString(StrArrRe,StrRe,'|'); //查看是tuxedo服务请求还是日志存储请求
if(SameText(StrArrRe[0],'Log')) then
begin
try
DataModule_t.SaveLogInfo(StrArrRe[1],StrToInt(StrArrRe[2]),StrArrRe[3]);
MemoDealInfo.Lines.Add('<---'+DateTimeToStr(Now)+':已存储日志信息:'+StrRe);
except
Athread.Connection.DisconnectSocket;
AThread.Connection.Disconnect;
Exit;
end;
Athread.Connection.DisconnectSocket;
AThread.Connection.Disconnect;
end; //if log
if(SameText(StrArrRe[0],'Tuxedo')) then
begin
Stra:='13381260003';
Strb:='001662';
IntRe:=-9999;
IntRe:=User_Auth(Stra,Strb) ;//调用dll
try
AThread.Connection.WriteLn(inttostr(IntRe));
MemoDealInfo.Lines.Add('<---'+DateTimeToStr(Now)+':已处理Tuxedo请求:'+inttostr(IntRe));
except
Athread.Connection.DisconnectSocket;
AThread.Connection.Disconnect;
Exit;
end;
Athread.Connection.DisconnectSocket;
AThread.Connection.Disconnect;
end; //if tuxedo
end;// not AThread.Terminated
end;===============================================================================
第2种方法
procedure TPrm_Proxy.Button3Click(Sender: TObject);
var
Str2,Str3:pChar;
b_ok:integer;
begin Str2:='13381260003';
Str3:='001662';
b_ok:=-9999;
b_ok:=User_Auth(Str2,Str3) ; //调用dll
end;
用2种方法每次都成功的,可是第一种方法只有第一次调用会成功,第二次调用,要么就是dll里面的Tpinit失败,或者调用tuxedo服务失败!dll在C里面这么声明的extern "C" _declspec(dllexport) int User_Auth(char * cMobileNumber,char* cPwd);delphi里面静态掉的 function User_Auth(cMobileNumber:pChar;cPwd :pChar ):integer;cdecl;
external 'Tuxedo_Auth.dll'; 另外,里面用的是indy的IDTCPserver组件,工程里面还有ODAC组件,都是第三方的。现在定位了一天多了,还是一筹莫展,往高手不吝赐教,不然明天还得加班!
Var
StrRe:String;
StrArrRe:Array [0..19] of String;
StrMobileNumber,StrPwd:String;
Stra,Strb,Strc,Strd:pChar;
IntRe:integer; Handle: THandle;
Auth: TMyApp;
begin
if not AThread.Terminated and AThread.Connection.Connected then //注意这里
begin
StrRe:=AThread.Connection.ReadLn();
MemoDealInfo.Lines.Add('--->'+DateTimeToStr(Now)+':收到来自客户端'+ AThread.Connection.Socket.Binding.PeerIP+':'+inttoStr (AThread.Connection.Socket.Binding.PeerPort)+'的请求信息:'+StrRe); //拆分客户端传来的(日志、Tuxedo请求)信息A|B|C
SplitString(StrArrRe,StrRe,'|'); //查看是tuxedo服务请求还是日志存储请求
if(SameText(StrArrRe[0],'Log')) then
begin
try
DataModule_t.SaveLogInfo(StrArrRe[1],StrToInt(StrArrRe[2]),StrArrRe[3]);
MemoDealInfo.Lines.Add('<---'+DateTimeToStr(Now)+':已存储日志信息:'+StrRe);
except
Athread.Connection.DisconnectSocket;
AThread.Connection.Disconnect;
Exit;
end;
Athread.Connection.DisconnectSocket;
AThread.Connection.Disconnect;
end; //if log
if(SameText(StrArrRe[0],'Tuxedo')) then
begin
Stra:='13381260003';
Strb:='001662';
IntRe:=-9999;
IntRe:=User_Auth(Stra,Strb) ;//调用dll
try
AThread.Connection.WriteLn(inttostr(IntRe));
MemoDealInfo.Lines.Add('<---'+DateTimeToStr(Now)+':已处理Tuxedo请求:'+inttostr(IntRe));
except
Athread.Connection.DisconnectSocket;
AThread.Connection.Disconnect;
Exit;
end;
Athread.Connection.DisconnectSocket;
AThread.Connection.Disconnect;
end; //if tuxedo
end;// not AThread.Terminated
end;===============================================================================
第2种方法
procedure TPrm_Proxy.Button3Click(Sender: TObject);
var
Str2,Str3:pChar;
b_ok:integer;
begin Str2:='13381260003';
Str3:='001662';
b_ok:=-9999;
b_ok:=User_Auth(Str2,Str3) ; //调用dll
end;
用2种方法每次都成功的,可是第一种方法只有第一次调用会成功,第二次调用,要么就是dll里面的Tpinit失败,或者调用tuxedo服务失败!dll在C里面这么声明的extern "C" _declspec(dllexport) int User_Auth(char * cMobileNumber,char* cPwd);delphi里面静态掉的 function User_Auth(cMobileNumber:pChar;cPwd :pChar ):integer;cdecl;
external 'Tuxedo_Auth.dll'; 另外,里面用的是indy的IDTCPserver组件,工程里面还有ODAC组件,都是第三方的。现在定位了一天多了,还是一筹莫展,往高手不吝赐教,不然明天还得加班!
注释这行看看有没有问题
IntRe:=User_Auth(Stra,Strb) ;//调用dll 如果没有问题,说明问题出在这行,因为IdTCPServer_DB_TuxedoExecute是个线程回调函数,User_Auth函数引用的资源可能没有考虑线程同步或者资源有冲突,如果有dll的代码研究一下就能判断出来了否则在User_Auth(Stra,Strb)前后加个信号量同步一下线程看看还有没有问题
WaitForSingleObject如果注释了IntRe:=User_Auth(Stra,Strb) ;//调用dll 依然有问题说明问题不在dll函数上了,检查别的吧
SysUtils,
Winsock,
Windows;type
TParam=record
TrdId:integer;
Sckt:TSocket;
end; function User_Auth(cMobileNumber:pChar;cPwd :pChar ):integer;cdecl;
external 'Tuxedo_Auth.dll';function SplitString(var arstr: array of string; const Source: string; ch: Char): integer;
var
i, head: Integer;
begin
result := 0; if Source = '' then
begin
arstr[1] := '';
inc(result);
exit;
end; head := 1;
for i := 1 to length(Source) do
begin
if Source[i] = ch then
begin
arstr[result] := copy(Source, head, i - head);
head := i + 1;
inc(result);
end;
end;
arstr[result] := copy(Source, head, length(Source) - head + 1);
inc(result);
end;
/////////////////////////////////////////////////////////////////////////////
//子线程函数
function ChildThrd(p:Pointer):LongInt;stdcall;
var
PkLen:integer;
ThreadId:integer;
ASocket:TSocket;
buf:array[0..63] of char;
//StrArrRe:Array [0..19] of String;
r:integer;
a,b:pChar;
begin
Result:=0;
ThreadId:=TParam(p^).TrdId;
ASocket:=TParam(p^).Sckt;
Writeln('Thread '+IntToStr(ThreadId)+' Create');
PkLen:=1;
while PkLen>0 do
begin
FillChar(buf,SizeOf(buf),0);
PkLen:=Recv(ASocket,buf,SizeOf(buf),0); //接收数据
//-------------------------------------------------
a:='133########';
b:='0016##';
//-------------------------------------------------
r:=User_Auth(a,b); //调用dll
Writeln('result is :' +inttostr(r));
Write(buf);
if PkLen>0 then
begin
Send(ASocket,buf,PkLen,0);//发送数据
end;
end;
CloseSocket(ASocket); //关闭socket
Dispose(p);
Writeln('Thread \'+IntToStr(ThreadId)+' End\');
Writeln('Socket \'+IntToStr(ASocket)+' DisConnect\');
end;//主程序
var
MyWSA: WSAData;
Svr,Clt: TSockAddr;
NameLen:Integer;
hSocket,s: TSocket;
TimeOut:integer;
ThreadCount:integer;
hThread:Thandle;
ThreadID:DWord;
Param:^TParam;
begin
If WSAStartup(MAKEWORD(2,2), MyWSA) <> 0 Then //初始化
Begin
WSACleanup;
Writeln('WSAStartup() Fail\');
Exit;
end;
hSocket := Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //创建socket
If hSocket = INVALID_SOCKET Then
Begin
WSACleanup;
Writeln('Socket() Fail\');
Exit;
End;
Svr.sin_family := AF_INET;
Svr.sin_port := htons(9999); //server端口号为9999
Svr.sin_addr.S_addr := inet_addr(PChar('127.0.0.1'));//server的ip地址为127.0.0.1
If Bind(hSocket, Svr, SizeOf(Svr)) = SOCKET_ERROR Then //绑定socket
Begin
CloseSocket(hSocket);
WSACleanup;
Writeln('Bind() Fail\');
Exit;
end;
if Listen(hSocket,256) = SOCKET_ERROR Then //socket开始侦听,最大同时连接数为256个
begin
CloseSocket(hSocket);
WSACleanup;
Writeln('Listen() Fail\');
Exit;
end;
TimeOut:=3000;
ThreadCount:=0;
Writeln('Listening......\');
while true do
begin
NameLen:=SizeOf(Clt);
s:=Accept(hSocket,@Clt,@NameLen);//接受一个连接
if s = SOCKET_ERROR Then
begin
CloseSocket(hSocket);
WSACleanup;
Writeln('Accept() Fail\');
Exit;
end
else
begin
Writeln('Socket \'+IntToStr(s)+' Connect\');
if SetSockOpt(s,SOL_SOCKET,SO_RCVTIMEO,PChar(@TimeOut),SizeOf(TimeOut))=SOCKET_ERROR then //设置接收超时为3秒
begin
CloseSocket(s);
CloseSocket(hSocket);
WSACleanup;
Writeln('SetSockOpt() Fail\');
Exit;
end;
if SetSockOpt(s,SOL_SOCKET,SO_SNDTIMEO,PChar(@TimeOut),SizeOf(TimeOut))=SOCKET_ERROR then //设置发送超时为3秒
begin
CloseSocket(s);
CloseSocket(hSocket);
WSACleanup;
Writeln('SetSockOpt() Fail\');
Exit;
end;
new(Param);
Param^.TrdId:=ThreadCount;
Param^.Sckt:=s;
hThread:=CreateThread(nil,0,@ChildThrd,Param,0,ThreadID); //创建childthrd子线程
if hThread=0 then
begin
Writeln('CreateThread() Fail\');
end
else
begin
Inc(ThreadCount);
end;
end;
end;
CloseSocket(hSocket); //关闭socket
WSACleanup;
end.
tpinfo->flags = TPMULTICONTEXTS; //多线程
需要在初始化tuxedo连接时,指定多线程终于解决问题了,激动
tpinfo->flags = TPMULTICONTEXTS; //多线程需要在初始化Tuxedo连接时,指定支持多线程调用。终于解决了,开心!