回覆列表
  • 1 # 南風微涼稻花靜待

    設計思路

    本例包括一個伺服器端程式和一個客戶端程式。客戶端程式可以放到多個計算機上執行,同時與伺服器端進行連線通訊。

    本例的重點,一是演示客戶端與伺服器端如何通訊;二是當有多個客戶端同時連線到伺服器端時,伺服器端如何識別每個客戶端,並對請求給出相應的回覆。為了保證一個客戶端斷開連線時不影響其它客戶端與伺服器端的通訊,同時保證伺服器端能夠正確回覆客戶端的請求,在本例中聲明瞭一個記錄型別:

    type

    client_record=record

    CHandle:integer;//客戶端套接字控制代碼

    CSocket:TCustomWinSocket;//客戶端套接字

    CName:string;//客戶端計算機名稱

    CAddress:string;//客戶端計算機IP地址

    CUsed:boolean;//客戶端聯機標誌

    end;

    利用這個記錄型別資料儲存客戶端的資訊,同時儲存當前客戶端的連線狀態。其中,CHandle儲存客戶端套接字控制代碼,以便準確定位每個與伺服器端保持連線的客戶端;Csocket儲存客戶端套接字,透過它可以對客戶端進行回覆。Cused記錄當前客戶端是否與伺服器端保持連線。

    下面對元件ServerSocket和ClientSocket的屬性設定簡單說明。

    ServerSocket的屬性:

    ·Port,是通訊的埠,必須設定。在本例中設定為1025;

    ·ServerTypt,伺服器端讀寫資訊型別,設定為stNonBlocking表示非同步讀寫資訊,本例中採用這種方式。

    ·ThreadCacheSize,客戶端的最大連線數,就是伺服器端最多允許多少客戶端同時連線。本例採用預設值10。

    其它屬性採用預設設定即可。

    ClientSocket的屬性:

    ·Port,是通訊的埠,必須與伺服器端的設定相同。在本例中設定為1025;

    ·ClientType,客戶端讀寫資訊型別,應該與伺服器端的設定相同,為stNonBlocking表示非同步讀寫資訊。

    ·Host,客戶端要連線的伺服器的IP地址。必須設定,當然也可以在程式碼中動態設定。

    其它屬性採用預設設定即可。

    程式原始碼:

    ·伺服器端原始碼(uServerMain.pas):

    unituServerMain;

    interface

    uses

    Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,

    ScktComp,ToolWin,ComCtrls,ExtCtrls,StdCtrls,Buttons;

    const

    CMax=10;//客戶端最大連線數

    type

    client_record=record

    CHandle:integer;//客戶端套接字控制代碼

    CSocket:TCustomWinSocket;//客戶端套接字

    CName:string;//客戶端計算機名稱

    CAddress:string;//客戶端計算機IP地址

    CUsed:boolean;//客戶端聯機標誌

    end;

    type

    TfrmServerMain=class(TForm)

    ServerSocket:TServerSocket;

    ControlBar1:TControlBar;

    ToolBar1:TToolBar;

    tbConnect:TToolButton;

    tbClose:TToolButton;

    tbDisconnected:TToolButton;

    Edit1:TEdit;

    Memo1:TMemo;

    StatusBar:TStatusBar;

    proceduretbConnectClick(Sender:TObject);

    proceduretbDisconnectedClick(Sender:TObject);

    procedureServerSocketClientRead(Sender:TObject;Socket:TCustomWinSocket);

    procedureServerSocketListen(Sender:TObject;Socket:TCustomWinSocket);

    procedureServerSocketClientConnect(Sender:TObject;Socket:TCustomWinSocket);

    procedureServerSocketClientDisconnect(Sender:TObject;Socket:TCustomWinSocket);

    proceduretbCloseClick(Sender:TObject);

    procedureFormCreate(Sender:TObject);

    procedureFormClose(Sender:TObject;varAction:TCloseAction);

    procedureServerSocketGetSocket(Sender:TObject;Socket:Integer;

    varClientSocket:TServerClientWinSocket);

    procedureServerSocketClientError(Sender:TObject;

    Socket:TCustomWinSocket;ErrorEvent:TErrorEvent;

    varErrorCode:Integer);

    private

    {

    Privatedeclarations

    }

    public

    {

    Publicdeclarations

    }

    session:array[0..CMax]ofclient_record;//客戶端連線陣列

    Sessions:integer;//客戶端連線數

    end;

    var

    frmServerMain:TfrmServerMain;

    implementation

    {$R*.DFM}

    //開啟套接字連線,並使套接字進入監聽狀態

    procedureTfrmServerMain.tbConnectClick(Sender:TObject);

    begin

    ServerSocket.Open;

    end;

    //關閉套接字連線,不再監聽客戶端的請求

    procedureTfrmServerMain.tbDisconnectedClick(Sender:TObject);

    begin

    ServerSocket.Close;

    StatusBar.Panels[0].Text:="伺服器套接字連線已經關閉,無法接受客戶端的連線請求.";

    end;

    //從客戶端讀取資訊

    procedureTfrmServerMain.ServerSocketClientRead(Sender:TObject;Socket:TCustomWinSocket);

    var

    i:integer;

    begin

    //將從客戶端讀取的資訊新增到Memo1中

    Memo1.Lines.Add(Socket.ReceiveText);

    fori:=0tosessionsdo

    begin

    //取得匹配的客戶端

    ifsession[i].CHandle=Socket.SocketHandlethen

    begin

    session[i].CSocket.SendText("回覆客戶端"+session[i].CAddress+"==>"+Edit1.Text);

    end;

    end;

    end;

    //伺服器端套接字進入監聽狀態,以便監聽客戶端的連線

    procedureTfrmServerMain.ServerSocketListen(Sender:TObject;Socket:TCustomWinSocket);

    begin

    StatusBar.Panels[0].Text:="等待客戶端連線...";

    end;

    //當客戶端連線到伺服器端以後

    procedureTfrmServerMain.ServerSocketClientConnect(Sender:TObject;

    Socket:TCustomWinSocket);

    var

    i,j:integer;

    begin

    j:=-1;

    fori:=0tosessionsdo

    begin

    //在原有的客戶端連線陣列中有中斷的客戶端連線

    ifnotsession[i].CUsedthen

    begin

    session[i].CHandle:=Socket.SocketHandle;//客戶端套接字控制代碼

    session[i].CSocket:=Socket;//客戶端套接字

    session[i].CName:=Socket.RemoteHost;//客戶端計算機名稱

    session[i].CAddress:=Socket.RemoteAddress;//客戶端計算機IP

    session[i].CUsed:=True;//連線陣列當前位置已經佔用

    Break;

    end;

    j:=i;

    end;

    ifj=sessionsthen

    begin

    inc(sessions);

    session[j].CHandle:=Socket.SocketHandle;

    session[j].CSocket:=Socket;

    session[j].CName:=Socket.RemoteHost;

    session[j].CAddress:=Socket.RemoteAddress;

    session[j].CUsed:=True;

    end;

    StatusBar.Panels[0].Text:="客戶端"+Socket.RemoteHost+"已經連線";

    end;

    //當客戶端斷開連線時

    procedureTfrmServerMain.ServerSocketClientDisconnect(Sender:TObject;

    Socket:TCustomWinSocket);

    var

    i:integer;

    begin

    fori:=0tosessionsdo

    begin

    ifsession[i].CHandle=Socket.SocketHandlethen

    begin

    session[i].CHandle:=0;

    session[i].CUsed:=False;

    Break;

    end;

    end;

    StatusBar.Panels[0].Text:="客戶端"+Socket.RemoteHost+"已經斷開";

    end;

    //關閉視窗

    procedureTfrmServerMain.tbCloseClick(Sender:TObject);

    begin

    Close;

    end;

    procedureTfrmServerMain.FormCreate(Sender:TObject);

    begin

    sessions:=0;

    end;

    procedureTfrmServerMain.FormClose(Sender:TObject;varAction:TCloseAction);

    begin

    ServerSocket.Close;

    end;

    //當客戶端正在與伺服器端連線時

    procedureTfrmServerMain.ServerSocketGetSocket(Sender:TObject;

    Socket:Integer;varClientSocket:TServerClientWinSocket);

    begin

    StatusBar.Panels[0].Text:="客戶端正在連線...";

    end;

    //客戶端發生錯誤

    procedureTfrmServerMain.ServerSocketClientError(Sender:TObject;

    Socket:TCustomWinSocket;ErrorEvent:TErrorEvent;

    varErrorCode:Integer);

    begin

    StatusBar.Panels[0].Text:="客戶端"+Socket.RemoteHost+"發生錯誤!";

    ErrorCode:=0;

    end;

    end.

  • 中秋節和大豐收的關聯?
  • 安全防範設計評估師的報考條件?