• Delphi与Socket


    一、Delphi与Socket
    计算机网络是由一系列网络通信协议组成的,其中的核心协议是传输层的TCPIP和UDP协议。TCP是面向连接的,
    通信双方保持一条通路,好比目前的电话线,使用telnet登陆BBS,用的就是TCP协议;UDP是无连接的,通信双方都不保持对方的状态,
    浏览器访问Internet时使用的
    HTTP协议就是基于UDP协议的。TCP和UDP协议都非常复杂,
    尤其是TCP协议,为了保证网络传输的正确性和有效性,必须进行一系列复杂的纠错和排序等处理。

    Socket是建立在传输层协议(主要是TCP和UDP)上的一种套接字规范,最初是由美国加州Berkley大学提出,
    它定义两台计算机间进行通信的规范(也是一种编程规范),如果说两台计算机是利用一个“通道“进行通信,
    那么这个“通道“的两端就是两个套接字。套接字屏蔽了底层通信软件和具体操作系统的差异,使得任何两台安装
    了TCP协议软件和实现了套接字规范的计算机之间的通信成为可能。
    微软的Windows
    Socket规范(简称winsock)对Berkley的套接字规范进行了扩展,利用标准的Socket的方法,
    可以同任何平台上的Socket进行通信;利用其扩展,可以更有效地实现在Windows平台上计算机间的通信。在Delphi中,
    其底层的Socket也应该是Windows的
    Socket。Socket减轻了编写计算机间通信软件的难度,但总的说来还是相当复杂的
    (这一点在后面具体会讲到);Inprise在Delphi中对
    Windows
    Socket进行了有效的封装,使得用户可以很方便地编写网络通信程序。
    下面我们实例解读在Delphi中如何利用Socket编写通信程序。
    二、利用Delphi编写Socket通信程序。
    下面是一个简单的Socket通信程序,其中客户机和服务机是同一个程序,当客户机(服务器)在一个memo1中输入一段文字然后敲入回车,
    该段文字就可以显示在服务器(客户机)的memo2中,反之亦成立。具体步骤如下:
    1、新建一个form,任意命名,不妨设之为chatForm;放上一个MainMenu(在Standard栏中),建立ListenItem、

    ConnectItem、Disconnect和Exit菜单项;在从Internet栏中选择TServerSocket、TClientSocket
    添加到chatForm中,
    其中把TClientSocket的名字设为ClientSocket,
    port设为1025,默认的active为false;把TServerSocket的名字设为ServerSocket,
    port设为1025,默认的active为false,其他的不变;再放入两个memo,一个命名为memo1,另外一个命名为memo2,其中把memo2的color
    设置为灰色,因为主要用来显示对方的输入。下面我们一边编写代码一边解释原因。
    2、双击ListemItem。写入如下代码:
    procedure
    TChatForm.ListenItemClick(Sender TObject);
    begin
    ListenItem.Checked = not
    ListenItem.Checked;
    if ListenItem.Checked
    then
    begin
    ClientSocket.Active = False;
    ServerSocket.Active =
    True;
    end
    else
    begin
    if ServerSocket.Active
    then
    ServerSocket.Active =
    False;
    end;
    end;
    该程序段的说明如下:当用户选择ListemItem时,该ListenItem取反,如果选中的话,说明处于Listen状态,读者要了解的是:
    listen是Socket作为Server时一个专有的方法,如果处于listen,则ServerSocket设置为活动状态;否则,取消
    listen,
    则关闭ServerSocket。实际上,只有用户一开始选择该菜单项,表明该程序用作Server。反之,如果用户选择
    ConnectItem,
    则必然作为Client使用。
    3、双击ConnectItem,敲入以下代码。
    procedure
    TChatForm.ConnectItemClick(Sender TObject);
    begin
    if ClientSocket.Active
    then ClientSocket.Active = False;
    if InputQuery('Computer to connect to',
    'Address Name', Server) then
    if Length(Server) 0 then
    with ClientSocket
    do
    begin
    Host = Server;
    Active = True;
    ListenItem.Checked =
    False;
    end;
    end;
    这段程序的主要功能就是当用户选择ConnectItem菜单项时,设置应用程序为客户机,弹出input框,
    让用户输入服务器的地址。这也就是我们不一开始固定ClientSocket的host的原因,这样用户可以动态地连接不同的服务器
    。读者需要了解的是主机地址只是Socket作为客户机时具有的一个属性,Socket作为服务器时“一般“不用地址,因为它同本机绑定。
    4、在memo1的keydown方法中写入如下代码:
    procedure
    TChatForm.Memo1KeyDown(Sender TObject; var Key Word;
    Shift
    TShiftState);
    begin
    if Key = VK_Return then
    if IsServer
    then
    ServerSocket.Socket.Connections[0].SendText(Memo1.Lines[Memo1.Lines.Count
    - 1])
    else
    ClientSocket.Socket.SendText(Memo1.Lines[Memo1.Lines.Count -
    1]);
    end;
    该段代码的作用很明显,就是开始发消息了。其中如果是Server的话,它只向第一个客户机发消息,
    由于一个服务器可以连接多个客户机,而同客户机的每一个连接都由一个Socket来维持,因此ServerSocket.Socket.Connnections
    数组中存储的就是同Client维持连接的Socket。在标准Socket中,服务器方的Socket通过accept()方法的返回值获取维持同客户机
    连接的Socket,而发送、接受消息的方法分别为send(sendto)和recv(recvfrom),
    Delphi对此进行了封装。
    5、其余代码的简要介绍。
    procedure TChatForm.ServerSocketAccept(Sender
    TObject;
    Socket TCustomWinSocket);
    begin
    IsServer =
    True;
    end;
    ServerSocket的Accept方法,当客户机第一次连接时完成,通过其参数可以认为,它是在标准的accept方法后执行的,
    因为有TCustomWinSocket这个参数类型,它应该是标准Server方Socket的返回值。

    procedure
    TChatForm.ClientSocketRead(Sender TObject;
    Socket
    TCustomWinSocket);
    begin
    Memo2.Lines.Add(Socket.ReceiveText);
    end;

    procedure
    TChatForm.ServerSocketClientRead(Sender TObject;
    Socket
    TCustomWinSocket);
    begin
    Memo2.Lines.Add(Socket.ReceiveText);
    end;
    这两段代码分别是服务器方和客户机方在收到对方的消息时,由Delphi触发的,作用是在memo2中显示收到的消息。
    其中,
    ClientSocketRead中的Socket实际上就是Socket本身,而在ServerSocketClientRead中的Socket实际上是
    ServerSocket.Socket.Connection[]中的某个Socket。不过在Delphi中,对服务器方的Socket进行了有效的封装。
    procedure
    TChatForm.ServerSocketClientConnect(Sender TObject;
    Socket
    TCustomWinSocket);
    begin
    Memo2.Lines.Clear;
    end;
    procedure
    TChatForm.ClientSocketDisconnect(Sender TObject;
    Socket
    TCustomWinSocket);
    begin
    ListenItemClick(nil);
    end;
    这两段比较简单。其中ServerSocketClientConnect在ServerSocket收到一个新的连接时触发。而ClientSocketDisconnect
    在ClientSocket发出Disconncet时触发。

    procedure
    TChatForm.Exit1Click(Sender
    TObject);
    begin
    ServerSocket.Close;
    ClientSocket.Close;
    Close;
    end;
    procedure
    TChatForm.Disconnect1Click(Sender TObject);
    begin
    ClientSocket.Active =
    False;
    ServerSocket.Active =
    True;
    end;
    第一段为关闭应用程序。在标准Socket中,每个Socket在关闭时,必须调用closesocket()方法,否则系统不会释放资源。而在
    ServerSockt.Close和ClientSocket.Close中,系统内部肯定调用了closesocket()方法。
    三、标准Socket与Delphi中的Socket。
    标准的Socket的应用程序框架如下:
    Server方:
    Socket()[ 新建一个Socket]--Bind()[ 同服务器地址邦定 ]--Listen() --Accept()--block
    wait--read()[接受消息,在windows平台中,方法为send(TCP),或者是sendto(UDP)]--处理服务请求--Write()[发送消息,在windows平台中,方法为send(TCP),
    或者为sendto(UDP)。
    Client方相对简单:Socket()--Connect()[通过一定的port连接特定的服务器,这是与服务器建立连接]--Write()--Read()。
    Socket可以是基于TCP的,也可以是基于UDP,同时Socket甚至建立在其他的协议,比如IPXSPX,DECNet等。在新建一个
    Socket时,
    可以指定新建何类Socket。Bind()用来同服务器的地址邦定,如果一个主机只有一个IP地址,实际上邦定的作用就相对多余了。

    Listen()开始监听网络,Accept()用于接受连接,其返回值是保持同客户机联系的Socket。
    在Delphi中,对于Windows中的Socket进行了有效的封装。在Delphi中,按其继承关系,可以分层两类:
    一、TComponent--TAbstractSocket--TCustomSocket--TCustomServerSocket--TServerSocket
    TComponent--TAbstractSocket--TCustomSocket--TClientSocket
    二、直接从TObject继承过来
    TObject--TCustomWinSocket--TServerWinSocket
    TObject--TCustomWinSocket--TClientWinSocket
    TObject--TCustomWinSocket--TServerClientWinSocket
    可以看出第一类建立在TCustomSocket基础上,第二类建立在TCustomWinSocket的基础上。第一类建立在TComponet的基础上,
    第二类直接构建在TObject基础上。因此如果用户非常熟悉Socket并且想要编写控制台程序时,可以使用TCustomWinScoket
    类。
    同uses中可以看出,它们都在ScktComp.pas中实现,而在schtComp.pas中,则包含了winsock.pas文件,如果继续深入winsock文件,
    在其中可以发现所有的Windows
    Socket的基本方法。

    实际上,如果你了解了标准Socket的应用程序框架,对于使用Delphi编写Socket应用程序也就得心应手了;这不是说你必须了解复杂的
    Socket中的标准函数,也没有必要,因为Delphi已经为你做了很好的封装了,这也正是Delphi的强势所在,你只要了解那么一点点的基本框架。
    这是我对Delphi中的Socket应用的理解,不足之处希望大家指正。同时也乐于为大家解答Delphi中有关Socket的问题

  • 相关阅读:
    windows下Yarn安装与使用(两种方法)
    git配置公钥---解决码云出现git@gitee.com: Permission denied (publickey)
    npm使用国内镜像的两种方法
    【LeetCode】33. Search in Rotated Sorted Array (4 solutions)
    【LeetCode】83. Remove Duplicates from Sorted List
    【LeetCode】82. Remove Duplicates from Sorted List II
    【LeetCode】85. Maximal Rectangle
    【LeetCode】84. Largest Rectangle in Histogram
    【LeetCode】87. Scramble String
    【LeetCode】162. Find Peak Element (3 solutions)
  • 原文地址:https://www.cnblogs.com/yplong/p/3149980.html
Copyright © 2020-2023  润新知