学习indy组件
學(xué)習(xí)indy組件
1、學(xué)習(xí)indy組件之一idhttp的使用方法,學(xué)習(xí)定時器用法,學(xué)習(xí)分析html頁面,程序容錯處理
預(yù)備知識 IdHTTP組件是Indy組件的一部分,主要用于實現(xiàn)讀取HTTP服務(wù)器的資源,可以實現(xiàn)瀏覽器的網(wǎng)絡(luò)功能。
IdHTTP是從TIdCustomHTTP繼承來的,基本上也就是換了一個比較簡單的名字給類和屬性而已,它本身沒有自己的函數(shù)和過程,全是從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、異常響應(yīng)為開發(fā)者提供了一個按自己的需要進(jìn)行異常處理的機(jī)制。主要異常處理有兩種: try except end
try finally
try …except …end形成了一個異常響應(yīng)保護(hù)塊。與finally不同的是:正常情況下except 后面的語句并不被執(zhí)行,而當(dāng)異常發(fā)生時程序自動跳到except,進(jìn)入異常響應(yīng)處理模塊。當(dāng)異常被響應(yīng)后異常類自動清除。相關(guān)文章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('估計是成功了'); //發(fā)送完畢記錄
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if timer1.Enabled=false then
begin
timer1.Interval:=strtoint(Edit4.Text); //設(shè)定攻擊間隔
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); //按照設(shè)定的時間間隔自動點擊發(fā)送按鈕
end;
end.
?
--------------------------------------------------------------------------------
關(guān)于Indy Tcpserver和Tcpclient
--------------------------------------------------------------------------------
用了Indy以后我不擔(dān)心多線程的問題。我的客戶端和服務(wù)器端需要多次傳送不同性質(zhì)的數(shù)據(jù),所以服務(wù)器端是否要使用循環(huán)代碼讀取客戶端的內(nèi)容?客戶端通過發(fā)送不同的前綴讓服務(wù)器知道并接收其后的數(shù)據(jù)。請高手解答。
--------------------------------------------------------------------------------
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服務(wù) [閱讀全文(34) | 回復(fù)(1) | 引用通告(0) | 編輯]?
?
?
今天終于弄出來了,適用INDY的sendcmd,試驗過各種參數(shù),包括那個不明確要求結(jié)果的-1,但總是回答不能得到正確的回應(yīng),苦惱,后來沒有辦法,用了TCPCLIENT的低級方法iohandle,發(fā)出請求得到回應(yīng),還是那個要注意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
?
--------------------------------------------------------------------------------
?
關(guān)于Indy TCP Client控件的討論(二) [閱讀全文(21) | 回復(fù)(0) | 引用通告(0) | 編輯]?
?
?
其實Indy比較簡單,但是可以提供的方法太多了。我找了很久,才搞明白。
比方說這個讀取緩沖區(qū)的數(shù)據(jù),就有很多種方法。相對于TTcpClient的幾種方法來說,TIdTCPClient確實提供了多種選擇,不仔細(xì)研究真的容易糊涂(其實我比較喜歡用CurrentReadBuffer):
1、ReadFromStack
原型:function ReadFromStack(const ARaiseExceptionIfDisconnected: boolean; const ATimeout: integer; const AUseBuffer: boolean; ADestStream: TIdBuffer): integer; virtual;
用于判斷緩沖區(qū)里是否還有數(shù)據(jù)可讀,返回值:Integer - Number of bytes read.
2、CurrentReadBuffer
原型:function CurrentReadBuffer: string;
用于讀取Socket數(shù)據(jù)到緩沖區(qū),注意返回為String類型,如果直接顯示該String的數(shù)據(jù),對于/0之后的數(shù)據(jù)可能看不到,因此要讀取所有的數(shù)據(jù),還必須利用CurrentReadBufferSize()判斷該String的長度。
返回值:String - Contents of the Indy buffer.
3、GetResponse
原型:function GetResponse(const AAllowedResponses: Array of SmallInt): SmallInt; virtual;
對于簡單的命令應(yīng)答可以使用這個方法獲取應(yīng)答消息,返回值:SmallInt - The numeric response number.
4、ReadBuffer
原型:procedure ReadBuffer(var ABuffer; const AByteCount: Longint);
讀取指定數(shù)目的字節(jié)到緩沖區(qū)ABuffer,注意它會調(diào)用 ReadFromStack 以檢查緩沖區(qū)里的數(shù)據(jù)是否少于AByteCount
5、ReadInteger
原型:function ReadInteger(const AConvert: boolean): Integer;
從緩沖區(qū)中讀取整型數(shù)據(jù),它會調(diào)用ReadBuffer
6、ReadLn
原型:function ReadLn(const ATerminator: string; const ATimeout: integer): string; virtual;
讀取移行記錄,帶有一個TimeOut屬性,以防止在讀不到新行時死循環(huán)。返回值: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的意思,不必寫代碼的,
設(shè)置好SocksInfo的版本為Socks5,Host為代理的IP或Domain Name,Port為代理的端口,就可以讓IndyFTp通過協(xié)議為Socks5的代理服務(wù)器(防火墻)連接了,當(dāng)然別忘記設(shè)置好IdFTp的ProxySettings的ProxyType哦,還有其他的,關(guān)于User@站點的是要根據(jù)你的代理服務(wù)器(防火墻)的支持協(xié)議而定,一般有好幾種的:
?
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的底層命令發(fā)送聯(lián)接指令給代理服務(wù)器,由代理服務(wù)器解釋以后,建立到外部FTP服務(wù)器的連接,因為你是不能直接連接到外部FTP的,記得就是這時一定要用Passive模式,因為你在防火墻之后,只有你可以主動訪問外部,而外部不可以主動訪問你,關(guān)于HTTP Proxy是怎樣呢?也是差不多,就是復(fù)雜些:建立HTTP連接,通過SendCmd的底層命令發(fā)送Connect FTP:Port HTTP/1.0User-Agent: Mozilla/4.0 (compatible; LY FTP Explorer)Proxy-Connection: Keep-Alive等Http信息,是回車+換行,不管通過那一種連接,連接建立以后直接發(fā)送FTP命令就可以了,注意List和上傳/下載(stor/retr)的時候會建立新的連接,這時候也要用上述方法建立,否者無法成功建立新的數(shù)據(jù)端口,SendCMD是Indy的通用命令,用于發(fā)送原始的TCP數(shù)據(jù)(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協(xié)議返回代碼,
//詳細(xì)的看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
--------------------------------------------------------------------------------
?
通訊的問題(急得很)
--------------------------------------------------------------------------------
我現(xiàn)在要發(fā)送數(shù)據(jù)。
每次固定1k,數(shù)據(jù)是這樣的。先是一個結(jié)構(gòu)
Type Tcommand= record
? commandid : integer;
? datalength: integer;//表示后面還有多長字節(jié)的數(shù)據(jù)
? end;
后面就是要發(fā)送的數(shù)據(jù)了。
我想問要怎么轉(zhuǎn)化為字符流并用idTcpclient控件傳出去。
c中的發(fā)送和接收是可以這樣解決。可是在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發(fā)送都可以的
http://lysoft.7u7.net
--------------------------------------------------------------------------------
上面的高手能詳細(xì)的說清楚一下嗎?拜托
--------------------------------------------------------------------------------
類似如下的代碼,稍改一下,你就可以使用了。
? 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);
//模擬寫了幾個數(shù)據(jù)
??? 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;
--------------------------------------------------------------------------------
做個記號希望以后有用!:)
--------------------------------------------------------------------------------
謝謝你給我的答復(fù)。對我很有用。不過還有些不了解的地方。比如說pchar(integer(buf)+sizeof(Tcommand)) 等等。請賜教。
還有。為什么要用idtcpclient1.Socket.send,用其他的的如idtcpclient1.writebuffer()可以嗎?
還有我接收的時候要注意什么呢?(也用idtcpclient)
應(yīng)用是服務(wù)器端是用c寫,而客戶端是用delphi。謝謝了
--------------------------------------------------------------------------------
我沒用,看了一下幫助,沒看到writebuffer(),應(yīng)該也可以的。
pchar(integer(buf)+sizeof(Tcommand))
/
在d中,指針的運(yùn)算相對C要弱很多,所以很多C里面很方便的指針操作這里就會復(fù)雜得多。
相當(dāng)于C中的buf+sizeof(TCommand),
就是將buf指針通過integer轉(zhuǎn)換成整形的地址,加上sizeof(
Tcommand)偏移量,為得到的新地址,整形的地址,再將這個地址強(qiáng)制轉(zhuǎn)換成pChar指針。
接收的時候也沒什么特別的,就是解包的時候用我上面的取地址的方法就OK了。
--------------------------------------------------------------------------------
使用writebuffer()類似這樣發(fā)送:
var
? Command : Tcommand;
begin
? writebuffer(Command,SizeOf(Tcommand));
? writebuffer(數(shù)據(jù),SizeOf(數(shù)據(jù)));?
end;
接收的時候用readbuffer()
var
? Command : Tcommand;
begin
? readbuffer(Command,SizeOf(Tcommand));
? if command.commandid= 1 then
??? readbuffer(數(shù)據(jù)1,SizeOf(數(shù)據(jù)1))?
? else
??? readbuffer(數(shù)據(jù)2,SizeOf(數(shù)據(jù)2))?????
end;
--------------------------------------------------------------------------------
up
--------------------------------------------------------------------------------
WriteBuff可以,其實最簡單的是用WriteStream,Stream本身就包含了發(fā)送數(shù)據(jù)的大小,在前4個字節(jié),只要發(fā)送的數(shù)據(jù)不是太大,工作的很好。
?
http://www.uqa.cn/cnstu/3853/3853295.htm
總結(jié)
- 上一篇: tftp服务器怎么开启linux,Cen
- 下一篇: 我国IPTV研究目前已达到全球领先水平