線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:6119
推到 Plurk!
推到 Facebook!

VCL How To - InterNet 元件篇

 
bruce0211
版主


發表:157
回覆:668
積分:279
註冊:2002-06-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2002-08-10 17:30:17 IP:210.208.xxx.xxx 未訂閱
元件名稱: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
系統時間:2024-04-27 0:34:21
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!