其他语言

位置:IT落伍者 >> 其他语言 >> 浏览文章

利用Delphi编写Socket通信程序


发布日期:2022年09月22日
 
利用Delphi编写Socket通信程序
笔者在工作中遇到对局域网中各工作站与服务器之间进行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               

上一篇:Delphi编程技巧集锦

下一篇:Delphi面向对象编程的20条规则