indy的ftp控件idftp也有bug
公司里有一个服务使用ftp方式做数据传输,于是在服务程序中使用indy的ftp控件做数据传输,一段时间的运行发现在传输过程中由于某种不知道原因情况下的网络掉线会导致程序会死翘翘,仔细分析了程序的逻辑,没有发现问题,根据记录下的日志文件,发现死翘翘前在做ftp文件传输处理,但是对其的try except end异常保护块没有记录下异常,遂开始怀疑使用的idftp控件问题,因为以前使用idTCPClient的时侯也碰到过问题。
使用google搜索关键字idftp bug 发现 http://groups.google.com.hk/group/borland.public.delphi.internet.winsock/browse_thread/thread/7b65058aa344137f/070b497000a0ea46?fwc=1 有讲到这个问题,是由于idftp在数据端口传输数据时忘记了设置连接的ReadTimeout 属性值造成。
原文作者在 interalGet函数中打了一下补丁,不过分析了一下,发现原文作者只打了interalGet中的主动传输方式部分代码,被动(passive)传输方式以及interalPut函数中也存在同样问题的代码没有打补丁。
仔细看了一下代码,发现只要给InitDataChannel函数打下补丁就可,他在interalGet和interalPut函数中的主被动方式中都有使用。
-
procedure TIdFTP.InitDataChannel;
-
begin
-
FDataChannel.SendBufferSize := SendBufferSize;
-
FDataChannel.RecvBufferSize := RecvBufferSize;
-
FDataChannel.OnWork := OnWork;
-
FDataChannel.OnWorkBegin := OnWorkBegin;
-
FDataChannel.OnWorkEnd := OnWorkEnd;
-
-
// 添加的代码行 added line to fix the readtimeout bug
-
FDataChannel.ReadTimeout := Self.ReadTimeOut;
-
end;
———–
到此程序的分析修改就告一段落了,接下来就要让程序24×7不停的运行,以观察看是否还是否有类似问题发生了。
Popularity: 7% [?]
Related
在Delphi中使用indy SMTP发送gmail邮件
在Delphi中发送email很简单,发送ssl方式的gmail邮件也很简单,只要在使用的idSMTP上附加一个TIdSSLIOHandlerSocket 就可以了。
使用控件
-
procedure sendMail(sToMail, sSubject, sContent: String);
-
var
-
SMTP: TIdSMTP;
-
MailMessage: TIdMessage;
-
SSLSocket: TIdSSLIOHandlerSocket;
-
begin
-
SMTP := TIdSMTP.Create(nil);
-
SSLSocket := TIdSSLIOHandlerSocket.Create(nil);
-
MailMessage:= TIdMessage.Create(nil);
-
-
SMTP.IOHandler := SSLSocket;
-
SMTP.Port := 465;
-
SMTP.Host := 'smtp.gmail.com';
-
SMTP.AuthenticationType := atLogin;
-
-
smtp.UserName := 'SunnyYu2000';
-
smtp.Password := 'xxxxxx';
-
-
// 设置邮件的信息
-
MailMessage.From.Address := 'SunnyYu2000@gmail.com';
-
MailMessage.Recipients.EMailAddresses := sToMail;
-
MailMessage.Subject := sSubject;
-
MailMessage.Body.Text := sContent;
-
-
//发送邮件
-
try
-
try
-
SMTP.Connect(1000);
-
SMTP.Send(MailMessage);
-
ShowMessage('发送成功');
-
except on E:Exception do
-
ShowMessage('发送失败: ' + E.Message);
-
end;
-
finally
-
if SMTP.Connected then
-
SMTP.Disconnect;
-
end;
-
-
MailMessage.Free;
-
SSLSocket.Free;
-
SMTP.Free;
-
end;
编译后需要SSL动态库支持,支持库可以到Indy网站上下载到。
如果需要发送附件,可以再发送前添加如下类似代码
-
// 添加邮件的附件
-
TIdAttachment.Create(MailMessage.MessageParts, sAttachmentFileName);
————–
Indy需要的SSL支持dll下载地址 http://www.indyproject.org/Sockets/SSL.EN.aspx
Popularity: 7% [?]
Related
使用indy解析http协议的multipart上传数据
MMS彩信的数据附在Soap包后面,在正常解析soap的xml文件外,还需要对使用multipart/related编码上传的数据做解析处理,在indy中提供了解码类。
处理解码时,需要TIdMessageDecoderMIME负责实际的解码, TIdMIMEBoundary从头信息中做边界信息查找。
解码函数
-
procedure DecodeFormData(const sHeader: String; ASourceStream:TStream; sSavePath: String);
-
var
-
bEnd : Boolean;
-
sTmp: String;
-
Decoder: TIdMessageDecoderMIME;
-
ds: TStream;
-
begin
-
bEnd := False;
-
Decoder := TIdMessageDecoderMIME.Create(nil);
-
-
try
-
// 设置附件的边界
-
Decoder.MIMEBoundary := TIdMIMEBoundary.FindBoundary(sHeader);
-
Decoder.SourceStream := ASourceStream;
-
Decoder.ReadLn;
-
-
repeat
-
Decoder.ReadHeader; // 读入分块的Header信息
-
case Decoder.PartType of
-
mcptUnknown:
-
raise Exception.Create('Unknown form data detected');
-
mcptText:
-
begin
-
sTmp := Decoder.Headers.Values['Content-Type']; // 获取ContentType
-
ds := TMemoryStream.Create;
-
try
-
Decoder := Decoder.ReadBody(ds,bEnd);
-
// 如果取的数据仍然是由多块组成,则进行递归处理
-
if AnsiSameText(Fetch(Tmp, ';'),'multipart/mixed') then
-
DecodeFormData(sTmp, ds, sSavePath)
-
else
-
// 根据需要使用Dest的数据
-
finally
-
FreeAndNil(ds);
-
end;//try
-
end; // mcptText
-
-
mcptAttachment:
-
begin
-
// 处理附件的文件名
-
sTmp := ExtractFileName(Decoder.FileName);
-
if sTmp <> '' then
-
sTmp := sSavePath + sTmp
-
else
-
sTmp := MakeTempFilename(sSavePath);
-
-
ds := TFileStream.Create(sTmp, fmCreate);
-
try
-
Decoder := Decoder.ReadBody(ds,bEnd);
-
finally
-
FreeAndNil(ds);
-
end;//try
-
end; // mcptAttachment
-
end; // case
-
until (Decoder = nil) or bEnd;
-
finally
-
FreeAndNil(Decoder);
-
end;//try
-
end;
使用OnCreatePostStream 创建用来接受HttpPost数据的Stream
-
CreatePostStream(ASender: TIdPeerThread; var VPostStream: TStream);
-
begin
-
VPostStream := TMemoryStream.Create;
-
end;
最后在OnCommandGet中做解析处理
-
OnCommandGet(ASender: TIdPeerThread; ARequestInfo: TIdHttpRequestInfo; AResponseInfo: TIdHttpResponseInfo);
-
var
-
sContentType : String
-
begin
-
sContentType := ARequestInfo.ContentType;
-
-
if AnsiSameText(Fetch(S, ';'), 'multipart') then begin
-
DecodeFormData(sContentType, ARequestInfo.PostStream, 'c:temp');
-
end else
-
// 根据需要对请求数据做处理…
-
end;
Popularity: 6% [?]