熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Delphi編程 >> 正文

利用Delphi編寫Socket通信程序

2022-06-13   來源: Delphi編程 
筆者在工作中遇到對局域網中各工作站與服務器之間進行Socket通信的問題現在將本人總結出來的TServerSocket和TClientSocket兩個組件的基本用法寫出來希望與您分享

  ClientSocket組件為客戶端組件它是通信的請求方也就是說它是主動地與服務器端建立連接

  ServerSocket組件為服務器端組件它是通信的響應方也就是說它的動作是監聽以及被動接受客戶端的連接請求並對請求進行回復

  ServerSocket組件可以同時接受一個或多個ClientSocket組件的連接請求並與每個ClientSocket組件建立單獨的連接進行單獨的通信因此一個服務器端可以為多個客戶端服務

設計思路

  本例包括一個服務器端程序和一個客戶端程序客戶端程序可以放到多個計算機上運行同時與服務器端進行連接通信

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

type
client_record=record
CHandle: integer; //客戶端套接字句柄
CSocket:TCustomWinSocket; //客戶端套接字
CName:string; //客戶端計算機名稱
CAddress:string; //客戶端計算機IP地址
CUsed: boolean; //客戶端聯機標志
end;

  利用這個記錄類型數據保存客戶端的信息同時保存當前客戶端的連接狀態其中CHandle保存客戶端套接字句柄以便准確定位每個與服務器端保持連接的客戶端Csocket保存客戶端套接字通過它可以對客戶端進行回復Cused記錄當前客戶端是否與服務器端保持連接


屬性設置

  下面對組件ServerSocket和ClientSocket的屬性設置簡單說明

ServerSocket的屬性

· Port是通信的端口必須設置在本例中設置為

· ServerTypt服務器端讀寫信息類型設置為stNonBlocking表示異步讀寫信息本例中采用這種方式

· ThreadCacheSize客戶端的最大連接數就是服務器端最多允許多少客戶端同時連接本例采用默認值

  其它屬性采用默認設置即可

ClientSocket的屬性

· Port是通信的端口必須與服務器端的設置相同在本例中設置為

· ClientType客戶端讀寫信息類型應該與服務器端的設置相同為stNonBlocking表示異步讀寫信息

· Host客戶端要連接的服務器的IP地址必須設置當然也可以在代碼中動態設置

  其它屬性采用默認設置即可

程序源代碼

服務器端源碼(uServerMainpas)

unit uServerMain;
interface
uses
Windows Messages SysUtils Classes Graphics Controls Forms Dialogs
ScktComp ToolWin ComCtrls ExtCtrls StdCtrls Buttons;
const
CMax=; //客戶端最大連接數
type
client_record=record
CHandle: integer; //客戶端套接字句柄
CSocket:TCustomWinSocket; //客戶端套接字
CName:string; //客戶端計算機名稱
CAddress:string; //客戶端計算機IP地址
CUsed: boolean; //客戶端聯機標志
end;
type
TfrmServerMain = class(TForm)
ServerSocket: TServerSocket;
ControlBar: TControlBar;
ToolBar: TToolBar;
tbConnect: TToolButton;
tbClose: TToolButton;
tbDisconnected: TToolButton;
Edit: TEdit;
Memo: TMemo;
StatusBar: TStatusBar;
procedure tbConnectClick(Sender: TObject);
procedure tbDisconnectedClick(Sender: TObject);
procedure ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketListen(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure tbCloseClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure ServerSocketGetSocket(Sender: TObject; Socket: Integer;
var ClientSocket: TServerClientWinSocket);
procedure ServerSocketClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
private
{ Private declarations }
public
{ Public declarations }
session: array[CMax] of client_record; //客戶端連接數組
Sessions: integer; //客戶端連接數
end;
var
frmServerMain: TfrmServerMain;
implementation
{$R *DFM}
//打開套接字連接並使套接字進入監聽狀態
procedure TfrmServerMaintbConnectClick(Sender: TObject);
begin
ServerSocketOpen ;
end;
//關閉套接字連接不再監聽客戶端的請求
procedure TfrmServerMaintbDisconnectedClick(Sender: TObject);
begin
ServerSocketClose;
StatusBarPanels[]Text :=服務器套接字連接已經關閉無法接受客戶端的連接請求;
end;
//從客戶端讀取信息
procedure TfrmServerMainServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
i:integer;
begin
//將從客戶端讀取的信息添加到Memo
MemoLinesAdd(SocketReceiveText);
for i:= to sessions do
begin
//取得匹配的客戶端
if session[i]CHandle = SocketSocketHandle then
begin
session[i]CSocketSendText(回復客戶端+session[i]CAddress+ ==> +EditText);
end;
end;
end;
//服務器端套接字進入監聽狀態以便監聽客戶端的連接
procedure TfrmServerMainServerSocketListen(Sender: TObject;
Socket: TCustomWinSocket);
begin
StatusBarPanels[]Text :=等待客戶端連接;
end;
//當客戶端連接到服務器端以後
procedure TfrmServerMainServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
ij:integer;
begin
j:=;
for i:= to sessions do
begin
//在原有的客戶端連接數組中有中斷的客戶端連接
if not session[i]CUsed then
begin
session[i]CHandle := SocketSocketHandle ;//客戶端套接字句柄
session[i]CSocket := Socket; //客戶端套接字
session[i]CName := SocketRemoteHost ; //客戶端計算機名稱
session[i]CAddress := SocketRemoteAddress ;//客戶端計算機IP
session[i]CUsed := True; //連接數組當前位置已經占用
Break;
end;
j:=i;
end;
if j=sessions then
begin
inc(sessions);
session[j]CHandle := SocketSocketHandle ;
session[j]CSocket := Socket;
session[j]CName := SocketRemoteHost ;
session[j]CAddress := SocketRemoteAddress ;
session[j]CUsed := True;
end;
StatusBarPanels[]Text := 客戶端 +SocketRemoteHost + 已經連接;
end;
//當客戶端斷開連接時
procedure TfrmServerMainServerSocketClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
var
i:integer;
begin
for i:= to sessions do
begin
if session[i]CHandle =SocketSocketHandle then
begin
session[i]CHandle :=;
session[i]CUsed := False;
Break;
end;
end;
StatusBarPanels[]Text :=客戶端 +SocketRemoteHost + 已經斷開;
end;
//關閉窗口
procedure TfrmServerMaintbCloseClick(Sender: TObject);
begin
Close;
end;
procedure TfrmServerMainFormCreate(Sender: TObject);
begin
sessions := ;
end;
procedure TfrmServerMainFormClose(Sender: TObject;
var Action: TCloseAction);
begin
ServerSocketClose ;
end;
//當客戶端正在與服務器端連接時
procedure TfrmServerMainServerSocketGetSocket(Sender: TObject;
Socket: Integer; var ClientSocket: TServerClientWinSocket);
begin
StatusBarPanels[]Text :=客戶端正在連接;
end;
//客戶端發生錯誤
procedure TfrmServerMainServerSocketClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
StatusBarPanels[]Text :=客戶端+SocketRemoteHost +發生錯誤!;
ErrorCode := ;
end;
end

客戶端源碼(uClientMainpas)

unit uClientMain;
interface
uses
Windows Messages SysUtils Classes Graphics Controls Forms Dialogs
ScktComp ComCtrls ToolWin ExtCtrls StdCtrls Buttons;
const
SocketHost = ; //服務器端地址
type
TfrmClientMain = class(TForm)
ControlBar: TControlBar;
ToolBar: TToolBar;
tbConnected: TToolButton;
tbSend: TToolButton;
tbClose: TToolButton;
tbDisconnected: TToolButton;
ClientSocket: TClientSocket;
Edit: TEdit;
Memo: TMemo;
StatusBar: TStatusBar;
btnSend: TBitBtn;
procedure tbConnectedClick(Sender: TObject);
procedure tbDisconnectedClick(Sender: TObject);
procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
procedure tbSendClick(Sender: TObject);
procedure tbCloseClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure ClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocketConnecting(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmClientMain: TfrmClientMain;
implementation
{$R *DFM}
//打開套接字連接
procedure TfrmClientMaintbConnectedClick(Sender: TObject);
begin
ClientSocketOpen ;
end;
//關閉套接字連接
procedure TfrmClientMaintbDisconnectedClick(Sender: TObject);
begin
ClientSocketClose;
end;
//接受服務器端的回復
procedure TfrmClientMainClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
MemoLinesAdd(SocketReceiveText);
end;
//發送信息到服務器端
procedure TfrmClientMaintbSendClick(Sender: TObject);
begin
ClientSocketSocketSendText(EditText);
end;
procedure TfrmClientMaintbCloseClick(Sender: TObject);
begin
Close;
end;
//設置要連接的服務器端地址
procedure TfrmClientMainFormShow(Sender: TObject);
begin
ClientSocketHost := SocketHost;
end;
//已經連接到服務器端
procedure TfrmClientMainClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
tbSendEnabled := True;
tbDisconnectedEnabled :=True;
btnSendEnabled := True;
StatusBarPanels[]Text := 已經連接到 + SocketRemoteHost ;
end;
//正在連接到服務器端
procedure TfrmClientMainClientSocketConnecting(Sender: TObject;
Socket: TCustomWinSocket);
begin
StatusBarPanels[]Text := 正在連接到服務器 ;
end;
//當斷開與服務器端的連接時發生
procedure TfrmClientMainClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
tbSendEnabled := False;
btnSendEnabled := False;
tbDisconnectedEnabled := False;
StatusBarPanels[]Text := 已經斷開與 + SocketRemoteHost + 的連接;
end;
procedure TfrmClientMainFormClose(Sender: TObject;
var Action: TCloseAction);
begin
ClientSocketClose ;
end;
//當與服務器端的連接發生錯誤時
procedure TfrmClientMainClientSocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
StatusBarPanels[]Text := 與服務器端的連接發生錯誤;
ErrorCode := ;
end;
end

小結

  上述方法是比較簡單的實現方法同時也是相對較容易理解的方法通過這個方法筆者成功實現了局域網內多個客戶端與服務器端進行Socket通信的功能同時可以保證一個客戶端的連接通信或是斷開都不影響其它客戶端的正常通信

附錄

  服務器端窗體和客戶端窗體及組件的屬性設置隊應的DFM文件

uServerMainpas對應的DFM文件(uServerMaindfm)
object frmServerMain: TfrmServerMain
Left =
Top =
BorderIcons = [biSystemMenu biMinimize]
BorderStyle = bsSingle
Caption = ServerSocket
ClientHeight =
ClientWidth =
Color = clBtnFace
FontCharset = DEFAULT_CHARSET
FontColor = clWindowText
FontHeight =
FontName = MS Sans Serif
FontStyle = []
OldCreateOrder = False
OnClose = FormClose
OnCreate = FormCreate
PixelsPerInch =
TextHeight =
object ControlBar: TControlBar
Left =
Top =
Width =
Height =
Align = alTop
AutoSize = True
TabOrder =
object ToolBar: TToolBar
Left =
Top =
Width =
Height =
ButtonHeight =
ButtonWidth =
Caption = ToolBar
EdgeInner = esNone
EdgeOuter = esNone
Flat = True
ShowCaptions = True
TabOrder =
object tbConnect: TToolButton
Left =
Top =
Caption = 連接
ImageIndex =
OnClick = tbConnectClick
end
object tbDisconnected: TToolButton
Left =
Top =
Caption = 斷開
ImageIndex =
OnClick = tbDisconnectedClick
end
object tbClose: TToolButton
Left =
Top =
Caption = 關閉
ImageIndex =
OnClick = tbCloseClick
end
end
end
object Edit: TEdit
Left =
Top =
Width =
Height =
TabOrder =
Text = 你好!
end
object Memo: TMemo
Left =
Top =
Width =
Height =
Align = alTop
TabOrder =
end
object StatusBar: TStatusBar
Left =
Top =
Width =
Height =
Panels = <
item
Width =
end>
SimplePanel = False
end
object ServerSocket: TServerSocket
Active = False
Port =
ServerType = stNonBlocking
OnListen = ServerSocketListen
OnGetSocket = ServerSocketGetSocket
OnClientConnect = ServerSocketClientConnect
OnClientDisconnect = ServerSocketClientDisconnect
OnClientRead = ServerSocketClientRead
OnClientError = ServerSocketClientError
Left =
end
end
uClientMainpas對應的DFM文件(uClientMaindfm)
object frmClientMain: TfrmClientMain
Left =
Top =
BorderIcons = [biSystemMenu biMinimize]
BorderStyle = bsSingle
Caption = ClientSocket
ClientHeight =
ClientWidth =
Color = clBtnFace
FontCharset = DEFAULT_CHARSET
FontColor = clWindowText
FontHeight =
FontName = MS Sans Serif
FontStyle = []
OldCreateOrder = False
Position = poScreenCenter
OnClose = FormClose
OnShow = FormShow
PixelsPerInch =
TextHeight =
object ControlBar: TControlBar
Left =
Top =
Width =
Height =
Align = alTop
AutoSize = True
TabOrder =
object ToolBar: TToolBar
Left =
Top =
Width =
Height =
ButtonHeight =
ButtonWidth =
Caption = ToolBar
EdgeInner = esNone
EdgeOuter = esNone
Flat = True
ShowCaptions = True
TabOrder =
object tbConnected: TToolButton
Left =
Top =
Caption = 連接
ImageIndex =
OnClick = tbConnectedClick
end
object tbSend: TToolButton
Left =
Top =
Caption = 發送
Enabled = False
ImageIndex =
OnClick = tbSendClick
end
object tbDisconnected: TToolButton
Left =
Top =
Caption = 斷開
Enabled = False
ImageIndex =
OnClick = tbDisconnectedClick
end
object tbClose: TToolButton
Left =
Top =
Caption = 退出
ImageIndex =
OnClick = tbCloseClick
end
end
end
object Edit: TEdit
Left =
Top =
Width =
Height =
TabOrder =
Text = 問候
end
object Memo: TMemo
Left =
Top =
Width =
Height =
Align = alTop
TabOrder =
end
object StatusBar: TStatusBar
Left =
Top =
Width =
Height =
Panels = <
item
Width =
end>
SimplePanel = False
end
object btnSend: TBitBtn
Left =
Top =
Width =
Height =
Caption = 發送
Enabled = False
TabOrder =
OnClick = tbSendClick
end
object ClientSocket: TClientSocket
Active = False
ClientType = ctNonBlocking
Port =
OnConnecting = ClientSocketConnecting
OnConnect = ClientSocketConnect
OnDisconnect = ClientSocketDisconnect
OnRead = ClientSocketRead
OnError = ClientSocketError
Left =
end
end
From:http://tw.wingwit.com/Article/program/Delphi/201311/8511.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.