亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

用Indy組件開發Socket應用程序

2019-11-17 05:12:09
字體:
來源:轉載
供稿:網友

  筆者在前一段的工作中,需要開發一套簡單的網絡數據傳輸程序。由于平時常用Delphi做點開發,故此次也不例外。Delphi 7中帶有兩套TCP Socket組件:Indy Socket組件(IdTCPClient和IdTCPServer)和Delphi原生的TCP Socket組件(ClientSocket和ServerSocket)。
但是,Borland已宣稱ClientSocket和ServerSocket組件即將被廢棄,建議用相應的Indy組件來代替。因此,筆者使用了Indy。本文在對Indy進行簡要介紹的基礎上,創建了一組簡單的TCP Socket數據傳輸應用來演示了Indy的使用方法。

  開放源代碼的Internet組件集——Internet Direct(Indy)Internet Direct(Indy)是一組開放源代碼的Internet組件,涵蓋了幾乎所有流行的Internet協議。Indy用Delphi編寫,被包含在Delphi 6,Kylix 1和C++ Builder 6及以上各個版本的Borland開發環境中。Indy曾經叫做WinShoes(雙關于WinSock——Windows的Socket庫),是由Chad Z. Hower領導的一群開發者構建的,可以從Indy的站點www.nevrona.com/indy上找到更多的信息并下載其新版本。到筆者撰寫本文時為止,Indy的最新穩定版是9.0.14,Indy 10也進入了Beta測試階段。

  Delphi 7中所帶的是Indy 9。在其的組件面板上,一共安裝有100多個Indy組件。使用這些組件你可以開發基于各種協議的TCP客戶和服務器應用程序,并處理相關的編碼和安全問題。你可以通過前綴Id來識別Indy組件。

  Indy是阻塞式(Blocking)的

  當你使用Winsock開發網絡應用程序時,從Socket中讀取數據或者向Socket寫入數據都是異步發生的,這樣就不會阻斷程序中其它代碼的執行。在收到數據時,Winsock會向應用程序發送相應的消息。這種訪問方式被稱作非阻塞式連接,它要求你對事件作出響應,設置狀態機,并通常還需要一個等待循環。

  與通常的Winsock編程方法不同的是,Indy使用了阻塞式Socket調用方式。阻塞式訪問更像是文件存取。當你讀取數據,或是寫入數據時,讀取和寫入函數將一直等到相應的操作完成后才返回。比如說,發起網絡連接只需調用Connect方法并等待它返回,假如該方法執行成功,在結束時就直接返回,假如未能成功執行,則會拋出相應的異常。同文件訪問不同的是,Socket調用可能會需要更長的時間,因為要讀寫的數據可能不會立即就能預備好(在很大程度上依靠于網絡帶寬)。

  阻塞式Socket并非惡魔(Evil

  長期以來,阻塞式Socket都遭到了毫無理由的攻擊。其實阻塞式Socket并非如通常所說的那樣可怕。這還要從Winsock的發展說起。

  當Socket被從Unix移植到Windows時,一個嚴重的問題立即就出現了。Unix支持fork,客戶程序和服務器都能夠fork新的進程,并啟動這些進程,從而能夠很方便地使用阻塞式Socket。而Windows 3.x既不支持fork也不支持多線程,當使用阻塞式Socket時,用戶界面就會被“鎖住”而無法響應用戶輸入。

  為克服Windows 3.x的這一缺陷,微軟在Winsock中加入了異步擴展,以使Winsock不會“鎖住”應用程序的主線程(也是唯一的線程)。然而,這需要了一種完全不同的編程方式。于是有些人為了掩飾這一弱點,就開始強烈地誹謗阻塞式Socket。

  當Win32出現的時候,它能夠很好地支持線程。但是既成的觀念已經很難更改,并且說出去的話也無法收回,因此對阻塞式Socket的誹謗繼續存在著。

  事實上,阻塞式Socket仍然是Unix實現Socket的唯一方式,并且它工作得很好。

  阻塞式Socket的優點

  歸結起來,在Windows上使用阻塞式Socket開發應用程序具有如下優點:

  編程簡單——阻塞式Socket應用程序很輕易編寫。所有的用戶代碼都寫在同一個地方,并且順序執行。
輕易向Unix移植——由于Unix也使用阻塞式Socket,編寫可移植的代碼就變得比較輕易。Indy就是利用這一點來實現其多平臺支持而又單一源代碼的設計。

  很好地利用了線程技術——阻塞式Socket是順序執行的,其固有的封裝特性使得它能夠很輕易地使用到線程中。

  阻塞式Socket的缺點

  事物都具有兩面性,阻塞式Socket也不例外。它的一個主要的缺點就是使客戶程序的用戶界面“凍結”。當在程序的主線程中進行阻塞式Socket調用時,由于要等待Socket調用完成并返回,這段時間就不能處理用戶界面消息,使得Update、Repaint以及其它消息得不到及時響應,從而導致用戶界面被“凍結”。 更多文章 更多內容請看Wlan組網----家庭專題專題,或 使用TIdAntiFreeze對抗“凍結


  Indy使用一個非凡的組件TIdAntiFreeze來透明地解決客戶程序用戶界面“凍結”的問題。TIdAntiFreeze在Indy內部定時中斷對棧的調用,并在中斷期間調用application.PRocessMessages方法處理消息,而外部的Indy調用繼續保存阻塞狀態,就似乎TIdAntiFreeze對象不存在一樣。你只要在程序中的任意地方添加一個TIdAntiFreeze對象,就能在客戶程序中利用到阻塞式Socket的所有優點而避開它的一些顯著缺點。

  Indy使用了線程技術

  阻塞式Socekt通常都采用線程技術,Indy也是如此。從最底層開始,Indy的設計都是線程化的。因此用Indy創建服務器和客戶程序跟在Unix下十分相似,并且Delphi的快速開發環境和Indy對WinSock的良好封裝使得應用程序創建更加輕易。

  Indy服務器模型

  一個典型的Unix服務器有一個或多個監聽進程,它們不停地監聽進入的客戶連接請求。對于每一個需要服務的客戶,都fork一個新進程來處理該客戶的所有事務。這樣一個進程只處理一個客戶連接,編程就變得十分輕易。

  Indy服務器工作原理同Unix服務器十分類似,只是Windows不像Unix那樣支持fork,而是支持線程,因此Indy服務器為每一個客戶連接分配一個線程。

  圖1顯示了Indy服務器的工作原理。Indy服務器組件創建一個同應用程序主線程分離的監聽線程來監聽客戶連接請求,對于接受的每一個客戶,都創建一個新的線程來為該客戶提供服務,所有與這一客戶相關的事務都由該線程來處理。

用Indy組件開發Socket應用程序(圖一)
圖1 Indy服務器工作原理

  使用組件TIdThreadMgrPool,Indy還支持線程池。 更多文章 更多內容請看Wlan組網----家庭專題專題,或 線程與Indy客戶程序

  Indy客戶端組件并未使用線程。但是在一些高級的客戶程序中,程序員可以在自定義的線程中使用Indy客戶端組件,以使用戶界面更加友好。

  簡單的Indy應用示例

  下面將創建一個簡單的TCP客戶程序和一個簡單的TCP服務器來演示Indy的基本使用方法。客戶程序使用TCP協議同服務器連接,并向服務器發送用戶所輸入數據。服務器支持兩條命令:DATA和QUIT。在DATA命令后跟隨要發送的數據,并用空格將命令字DATA和數據分隔開。

  表單布局

  建立一個項目組,添加一個客戶程序項目和一個服務器項目。客戶程序和服務器程序的表單布局如同2和圖3所示。客戶程序表單上放置了TIdTCPClient組件,服務器程序表單上放置了TIdTCPServer組件。為防止客戶程序“凍結”,還在其表單上放置TIdAntiFreeze組件。

用Indy組件開發Socket應用程序(圖二)
圖2 簡單的TCP客戶程序表單

用Indy組件開發Socket應用程序(圖三)
圖3 簡單的TCP服務器程序表單

  客戶程序和服務器程序的表單上都放置有TListBox組件,用來顯示通信記錄。

  客戶程序代碼

  客戶程序片斷如代碼列表1所示。

  代碼列表1

procedure TFormMain.BTnConnectClick(Sender: TObject);
begin
IdTCPClient.Host := EdtHost.Text;
IdTCPClient.Port := StrToInt(EdtPort.Text);
LbLog.Items.Add('正在連接 ' + EdtHost.Text + '...');
with IdTCPClient do
begin
try
Connect(5000);
try
LbLog.Items.Add(ReadLn());
BtnConnect.Enabled := False;
BtnSend.Enabled := True;
BtnDisconnect.Enabled := True;
except
LbLog.Items.Add('遠程主機無響應!');
IdTCPClient.Disconnect();
end;//end try
except
LbLog.Items.Add('無法建立到' + EdtHost.Text + '的連接!');
end;//end try
end;//end with
end;

procedure TFormMain.BtnSendClick(Sender: TObject);
begin
LbLog.Items.Add('DATA ' + EdtData.Text);
with IdTCPClient do
begin
try
WriteLn('DATA ' + EdtData.Text);
LbLog.Items.Add(ReadLn())
except
LbLog.Items.Add('發送數據失?。?);
IdTCPClient.Disconnect();
LbLog.Items.Add('同主機 ' + EdtHost.Text + ' 的連接已斷開!');
BtnConnect.Enabled := True;
BtnSend.Enabled := False;
BtnDisconnect.Enabled := False;
end;//end try
end;//end with
end;

procedure TFormMain.BtnDisconnectClick(Sender: TObject);
var
Received: string;
begin
LbLog.Items.Add('QUIT');
try
IdTCPClient.WriteLn('QUIT');
finally
IdTCPClient.Disconnect();
LbLog.Items.Add('同主機 ' + EdtHost.Text + ' 的連接已斷開!');
BtnConnect.Enabled := True;
BtnSend.Enabled := False;
BtnDisconnect.Enabled := False;
end;//end try
end;
  在“連接”按鈕事件響應過程中,首先根據用戶輸入設置IdTCPClient的主機和端口,并調用IdTCPClient的Connect方法向服務器發出連接請求。然后調用ReadLn方法讀取服務器應答數據。

  在“發送”按鈕事件響應過程中,調用WriteLn方法寫DATA命令,向服務器發送數據。

  在“斷開”按鈕事件響應過程中,向服務器發送QUIT命令,并調用Disconnect方法斷開連接。

  程序中還包含有通信信息記錄和異常處理的代碼。 更多文章 更多內容請看Wlan組網----家庭專題專題,或


  服務器程序代碼

  服務器程序片斷如代碼列表2所示。

  代碼列表2

procedure TFormMain.BtnStartClick(Sender: TObject);
begin
IdTCPServer.DefaultPort := StrToInt(EdtPort.Text);
IdTCPServer.Active := True;
BtnStart.Enabled := False;
BtnStop.Enabled := True;
LbLog.Items.Add('服務器已成功啟動!');
end;

procedure TFormMain.BtnStopClick(Sender: TObject);
begin
IdTCPServer.Active := False;
BtnStart.Enabled := True;
BtnStop.Enabled := False;
LbLog.Items.Add('服務器已成功停止!');
end;

procedure TFormMain.IdTCPServerConnect(AThread: TIdPeerThread);
begin
LbLog.Items.Add('來自主機 '
+ AThread.Connection.Socket.Binding.Peerip
+ ' 的連接請求已被接納!');
AThread.Connection.WriteLn('100: 歡迎連接到簡單TCP服務器!');
end;

procedure TFormMain.IdTCPServerExecute(AThread: TIdPeerThread);
var
sCommand: string;
begin
with AThread.Connection do
begin
sCommand := ReadLn();
FLogEntry := sCommand + ' 來自于主機 '
+ AThread.Connection.Socket.Binding.PeerIP;
AThread.Synchronize(AddLogEntry);
if AnsiStartsText('DATA ', sCommand) then
begin
FReceived := RightStr(sCommand, Length(sCommand)-5);
WriteLn('200: 數據接收成功!');
AThread.Synchronize(DisplayData);
end
else if SameText(sCommand, 'QUIT') then begin
FLogEntry := '斷開同主機 '
+ AThread.Connection.Socket.Binding.PeerIP
+ ' 的連接!';
AThread.Synchronize(AddLogEntry);
Disconnect;
end
else begin
WriteLn('500: 無法識別的命令!');
FLogEntry := '無法識別命令:' + sCommand;
AThread.Synchronize(AddLogEntry);
end;//endif
end;
end;

procedure TFormMain.DisplayData();
begin
EdtData.Text := FReceived;
end;

procedure TFormMain.AddLogEntry();
begin
LbLog.Items.Add(FLogEntry);
end;

  “啟動”按鈕設置IdTCPServer 的Active屬性為True來啟動服務器,“停止”按鈕設置Active屬性為False來關閉服務器。

  IdTCPServerConnect方法作為IdTCPServer 的OnCorrect事件響應過程,向客戶端發送歡迎信息。OnCorrect事件在一個客戶連接請求被接受時發生,為該連接創建的線程AThread被作為參數傳遞給IdTCPServerConnect方法。

  IdTCPServerExecute方法是IdTCPServer 的OnExecute事件響應過程。OnExecute事件在TIdPeerThread對象試圖執行其Run方法時發生。OnExecute事件與通常的事件有所不同,其響應過程是在某個線程上下文中執行的,參數AThread就是調用它的線程。這一點很重要,它意味著可能有多個OnExecute事件響應過程被同時執行。在連接被斷開或中斷前,OnExecute事件響應過程會被反復執行。

  在IdTCPServerExecute方法中,首先讀入一條指令,然后對指令進行判別。假如是DATA指令,就解出數據并顯示它。假如收到的是QUIT指令,則斷開連接。需要非凡指出的是,由于IdTCPServerExecute方法在某一線程上下文中執行,因此顯示數據和添加事件記錄都是將相應的方法傳遞給Synchronize調用來完成的。

  運行程序

  運行客戶端和服務器程序,按如下流程進行操作:

  1. 按服務器程序的“啟動”按鈕啟動服務器;

  2. 按客戶程序的“連接”按鈕,建立同服務器的連接;

  3. 在客戶程序的待發送數據編輯框中輸入“Hello, Indy!”,并按“發送”按鈕發送數據;

  4. 按客戶程序的“斷開”按鈕,斷開同服務器的連接;

  5. 按服務器程序的“停止”按鈕停止服務器。

  程序運行的結果如圖4和圖5所示。


用Indy組件開發Socket應用程序(圖四)
圖4 簡單的TCP客戶

用Indy組件開發Socket應用程序(圖五)
圖5 簡單的TCP服務器 更多文章 更多內容請看Wlan組網----家庭專題專題,


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
最新国产成人av网站网址麻豆| 亚洲网站在线观看| 久久精品国产亚洲精品2020| 青青久久av北条麻妃黑人| 成人精品久久av网站| 亚洲欧美三级在线| 91九色视频导航| 91精品视频免费| 91精品国产自产91精品| 国产日韩欧美黄色| 亚洲国产成人久久综合| 欧美性猛交xxxx乱大交| 国产精品直播网红| 欧美激情一级二级| 欧洲美女免费图片一区| 国产精品小说在线| 97精品视频在线| 国产精品极品在线| 韩国精品美女www爽爽爽视频| 国产精品高清网站| 亚洲国产精品资源| 成人国产精品久久久久久亚洲| 一本一本久久a久久精品牛牛影视| 成人激情电影一区二区| 久久免费国产视频| 欧美激情手机在线视频| 国产日韩精品在线播放| 亚洲久久久久久久久久| 国产香蕉一区二区三区在线视频| 欧美xxxx做受欧美.88| 日韩视频一区在线| 国产在线观看91精品一区| 欧美性理论片在线观看片免费| 国产精品极品美女在线观看免费| 在线观看欧美日韩| 亚洲成人a级网| 亚洲成av人片在线观看香蕉| 久久亚洲精品毛片| 亚洲乱码国产乱码精品精天堂| 日韩有码片在线观看| 久久亚洲一区二区三区四区五区高| 成人亚洲欧美一区二区三区| 国产午夜精品全部视频播放| 欧美视频裸体精品| 成人在线视频福利| 亚洲午夜性刺激影院| 成人激情电影一区二区| 第一福利永久视频精品| 欧美激情精品在线| 国产精品爽爽爽爽爽爽在线观看| 亚洲深夜福利视频| 欧美极品xxxx| 国产精品wwww| 77777少妇光屁股久久一区| 久久久在线视频| 欧美电影在线观看完整版| 久久久久国产精品免费| 日韩免费观看在线观看| 国产日韩在线亚洲字幕中文| 久久久精品中文字幕| 色伦专区97中文字幕| 欧美另类精品xxxx孕妇| 亚洲毛片在线看| 国内精品国产三级国产在线专| 综合网日日天干夜夜久久| 色哟哟入口国产精品| 欧美日韩国产丝袜另类| 亚洲a成v人在线观看| 欧美精品第一页在线播放| 91欧美精品成人综合在线观看| 人人爽久久涩噜噜噜网站| 国产福利精品av综合导导航| 色偷偷偷综合中文字幕;dd| 日韩欧美一区二区三区久久| 国产国语videosex另类| 久久久久久久激情视频| 91高潮在线观看| 欧美电影免费在线观看| 国产91在线高潮白浆在线观看| 疯狂做受xxxx欧美肥白少妇| 国产不卡av在线| 欧美亚洲日本黄色| 欧美成人激情视频免费观看| 日韩精品在线影院| 国产精品jizz在线观看麻豆| 久久偷看各类女兵18女厕嘘嘘| 精品久久久久久久久久久| 日韩理论片久久| 日韩a**站在线观看| 亚洲美女中文字幕| 日韩欧美国产高清91| 国产日韩欧美夫妻视频在线观看| 91手机视频在线观看| 中文字幕自拍vr一区二区三区| 欧美精品在线网站| 在线成人免费网站| 日韩美女av在线免费观看| 韩剧1988在线观看免费完整版| 久久综合国产精品台湾中文娱乐网| 亚洲国产天堂网精品网站| 秋霞成人午夜鲁丝一区二区三区| 久久久国产视频91| 欧美性生交大片免费| 国产精品678| 久久久91精品国产| 久久久久久91| 在线日韩欧美视频| 国产亚洲精品美女| 在线丨暗呦小u女国产精品| 国产精品伦子伦免费视频| 福利微拍一区二区| 欧美高清在线视频观看不卡| 日韩av色综合| 亚洲性日韩精品一区二区| 国产欧美精品日韩精品| 精品美女永久免费视频| 成人黄色午夜影院| 欧美性黄网官网| 欧美刺激性大交免费视频| 国产一区二区三区在线视频| 日本精品一区二区三区在线| 亚洲国产精品女人久久久| 精品高清一区二区三区| 日韩一区av在线| 国产区精品在线观看| 日本国产精品视频| 亚洲欧美另类人妖| 国产精品丝袜高跟| 亚洲999一在线观看www| 992tv成人免费影院| 亚洲色图狂野欧美| 亚洲色图18p| 国产精品美女久久久久久免费| 在线播放日韩欧美| 97精品国产97久久久久久春色| 欧美日韩中国免费专区在线看| 精品中文视频在线| 久久久久久高潮国产精品视| 国产精品视频久久| 亚洲欧美国产高清va在线播| 福利二区91精品bt7086| 亚洲欧美国产日韩中文字幕| 亚洲tv在线观看| 欧美成人精品h版在线观看| 91在线高清免费观看| 91在线|亚洲| 国产欧美精品va在线观看| 国产91在线播放九色快色| 欧美激情小视频| 91精品国产自产在线观看永久| 国产在线观看精品| 久久久成人av| 欧美专区国产专区| 欧美日韩一区二区三区在线免费观看| 国产精品国产三级国产aⅴ9色| 亚洲国产成人精品久久| 久久国产精品久久久久久| 欧美在线激情网| 欧美香蕉大胸在线视频观看| 亚洲一区二区三区777| 亚洲a成v人在线观看| 5566日本婷婷色中文字幕97| 亚洲2020天天堂在线观看| 欧美日韩一区二区三区在线免费观看|