VCL How To - InterNet 元件篇 |
|
bruce0211
版主 ![]() ![]() ![]() ![]() ![]() 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
元件名稱:TServerSocket,TClientSocket
文件版本:for Delphi
文件作者:Delphi K.Top 討論區站長 (http://delphi.ktop.com.tw) ●[元件簡介]
這兩個元件是成雙成對的,採用UDP的通訊協定,一個在Server端使用,一個在Client端使用,可以用來寫線上聊天室軟體,Delphi K.Top網站的DelphiChat軟體就是用此元件組完成的,但是筆者也曾經用來寫線上的遊戲,如連線下棋...等. 通常我們在主機端執行TServerSocket,執行後主機的IP Address就是Client端要連上的IP Address,而在TServerSocket中Port屬性設定的Port值就是Client端要連上的Port,在Client端電腦使用TClientSocket,設好它的Host與Port屬性值後,就可以用Active:=True連上主機. ●[重要屬性]
TServerSocket.Active:
設定為True代表打開主機端的通訊,最好不要在設計階段打開此屬性,要在執行階段打開,例如:在Form的Create事件中. TServerSocket.Port:
用來設定通訊所用的Port,要注意TClientSocket的Port要與主機的port一樣,還有像FTP採用UDP port 21、某些通訊軟體會有固定使用的port,不要與這些程式衝突了,Delphi內附的Chat範例程式採用1024 port供您參考使用. TClient.Active:
設定為True代表打開Client端的通訊,最好不要在設計階段打開此屬性,最好在執行階段打開,例如:在Form的Create事件中,還有設為True後通訊不會立刻打開,所以不可設為True後馬上傳資料. TClientSocket.address:
填上主機的網址,如:delphi.ktop.com.tw,不要加http喔! TClientSocket.host:
填上主機的IP Address,如:xxx.xxx.xxx.xxx,也是不要加http,若您的Server與Client都在同一台,您可以填上127.0.0.1用來做單機的測試,還有address屬性與host屬性是二選一的,設定其中一個就好. TClientSocket.Port:
通訊所用的Port,要注意TClientSocket的Port要設得與主機的port一樣. ●[重要事件]
TClient.OnClientConnect:
當有一個Client連上時會呼叫此事件,參數(Socket: TCustomWinSocket)會傳回Client的Socket通道資訊,您可以用Socket.SocketHandle得到這個通道的編號(是一個數值),您可以將它存起來,將來主機可以用TServerSocket.Socket.Connections[n].SocketHandle來判斷是那一個Client connection,然後再用TServerSocket.Socket.Connections[n].SendText(string)送資料給指定的Client端. TServerSocket.OnClientDisConnect:
當有一個Client端終止通訊時會呼叫此事件,您可在此用Socket參數來判斷是那一個Client離線. TServerSocket.OnClientError:
當有一個Client端通訊發生錯誤時會呼叫此事件. TServerSocket.OnClientRead:
當有一個Client端送資料給主機時會呼叫此事件,您可用Socket.ReceiveText來取出送來的資料. TClientSocket.OnConnect:
當Client端成功連上主機後會呼叫此事件,您可在此設定一個旗標,旗標設定後才可開始一切的通訊. TClientSocket.OnDisConnect:
當Client當與主機斷訊時會呼叫此事件. TClient.OnRead:
當主機送來一筆資料時會呼叫此事件,您可用Socket.ReceiveText來取出送來的資料,還有若主機端連續送來的兩筆資料時間間隔太短,有可能兩筆資料會被合併成一筆,這點在設計通訊程式時要特別注意. ●[重要方法]
ServerSocket.Active := True;//打開主機通訊
ClientSocket.Active := True;//打開Client端通訊
ServerSocket.Socket.ActiveConnections // 連上主機端的Client總數
ServerSocket.Socket.Connections[i] // 連上主機端的Client通道資訊
ClientSocket.Socket.SendText('ABC'); // Client端送訊息給主機
//以下方法可從主機傳訊息給所有的Client端
for i:=0 to ServerSocket.Socket.ActiveConnections-1 do
begin
ServerSocket.Socket.Connections[i].SendText('ABC');
end; ●[範例說明]
//******************************************************************* // 線上聊天室(Chat Server)程式示範 ********************************** //******************************************************************* unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ScktComp; type TForm1 = class(TForm) ServerSocket1: TServerSocket; Memo1: TMemo; Memo2: TMemo; procedure FormCreate(Sender: TObject); procedure ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket); procedure ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} // Form建立後就將Server通道開啟 procedure TForm1.FormCreate(Sender: TObject); begin ServerSocket1.Active:=True; // 打開通道 end; // 有Client連上主機 procedure TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket); var i:integer; begin memo1.lines.clear; // Memo1用來顯示目前所有的Client通道編號 for i:=0 to ServerSocket1.Socket.ActiveConnections-1 do // 一個一個Client找 begin if ServerSocket1.Socket.Connections[i].SocketHandle=Socket.SocketHandle then // 如果找到目前連上的通道 memo1.lines.add('*' inttostr(Socket.SocketHandle)) // 通道編號前面加一*號代表剛連上線的Client else memo1.lines.add(inttostr(ServerSocket1.Socket.Connections[i].SocketHandle)); // 通到編號加入memo1中 end; end; // 有Client與主機斷訊 procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); var i:integer; begin memo1.lines.clear; // Memo1用來顯示目前所有的Client通道編號 for i:=0 to ServerSocket1.Socket.ActiveConnections-1 do // 一個一個Client找 memo1.lines.add(inttostr(ServerSocket1.Socket.Connections[i].SocketHandle)); // 通到編號加入memo1中 memo1.lines.add('x' inttostr(Socket.SocketHandle)) // 通道編號前面加一x號代表剛離開的Client end; // 有Client送來訊息 procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var i:integer; str:string; begin str:=Socket.ReceiveText; // 一定要用一個變數str先存起來,不可直接使用receivetext Memo2.Lines.Add(str); // 將收到的訊息加入memo2中 for i:=0 to ServerSocket1.Socket.ActiveConnections-1 do // 一個一個Client找 begin ServerSocket1.Socket.Connections[i].SendText(str); // 將收的的訊息送給所有的Client端 end; end; end. //******************************************************************* // 線上聊天室(Chat Client)程式示範 ********************************** //******************************************************************* unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ScktComp, StdCtrls; type TForm1 = class(TForm) Button1: TButton; ClientSocket1: TClientSocket; Memo1: TMemo; Memo2: TMemo; procedure Button1Click(Sender: TObject); procedure Memo1KeyPress(Sender: TObject; var Key: Char); procedure ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket); procedure ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket); procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket); private { Private declarations } public { Public declarations } end; var Form1: TForm1; ClientOk:boolean=false; implementation {$R *.dfm} // 用來連上主機的Button procedure TForm1.Button1Click(Sender: TObject); var serverip:string; begin if InputQuery('連上主機', '請輸入主機的IP Address:', Serverip) then if Length(Serverip) > 0 then begin ClientSocket1.Host := Serverip; // 設定主機的IP Address ClientSocket1.Active := True; // 連上主機 end; end; // 主機已成功連上 procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket); begin caption:='已連上主機'; ClientOk:=true; end; // 主機斷訊 procedure TForm1.ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket); begin caption:='與主機斷訊'; ClientOk:=False; end; // 輸入訊息後按Enter procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char); begin if ClientOk then // 已連上主機 if Key = #13 then // 按了Enter begin ClientSocket1.Socket.SendText(Memo1.Lines.text); // 送訊息給主機 Key:=#0; // 清空這個Enter按鍵 memo1.clear; // 清空輸入的Memo1 end; end; // Client收到主機傳來的訊息 procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket); var str:string; begin str:=Socket.ReceiveText; // 讀出訊息 Memo2.Lines.Add(str); // 將訊息放入Memo2中 end; end.●[使用經驗] 若您的Server端有防火牆必需把UPD所用的Port開放出來,Client端才可以連的上,至於Client若有使用防火牆時,若為一般簡易的IP分享器為鎖進不鎖出,即使UPD的Port未開放,Client端還是可以順利連上主機,若為大企業用的高等FireWall時,UPD的Port未開放,Client有可能無法連上主機! 發表人 - bruce0211 於 2002/08/10 17:31:43 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |