zoukankan      html  css  js  c++  java
  • 用Delphi实现WinSocket高级应用


    用Delphi实现WinSocket高级应用

    默认分类   2009-12-19 16:48   阅读6   评论0  
    字号:    

    Socket通信在Windows 中是排队的形式由操作系统处理,而且接收方和发送方相互协同工作,否则就会造成数据丢失。因此,不能用类似于for 语句的循环来实现对多组数据的发送,更不能用循环语句来接收数据。比如,你可以用for 语句来实型若干文件的复制,这很普遍也很正常,但在 Socket编程以及大多数网络应用编程中都是行不通的,因为网络通信的基本方式是请求和应答。另外,和所有的通信编程一样,Socket编程也遵循数据分包传送这一基本规则。也就是说,在 Socket编程中,每次发送和接收一个包,以保证数据传输的安全性和稳定性,同时也不至于过多地占用系统资源。

    对于ClientSocket组件,从字面上就可以看出,它用于请求方。也就是说,它的动作是主动地建立连接。显然,ServerSocket组件用于响应方,它的动作是侦听以及被动接受连接。

    组件ClientSocket的属性是相对静态的,它和ServerSocket之间只是连接和断开的关系。并且仅当ServerSocket对其接受才表示建立连接。

    组件ServerSocket的属性是动态的。伴随着一个新的ClientSocket与之建立连接的同时,就会产生一个新的Socket与该ClientSocket对应,保持单独的连接,进行单独的通信。因此,在同一个 ServerSocket中,可以与多个ClientSocket保持同时连接和各自独立的通信。ServerSocket的属性 Socket.ActiveConnections用于表示客户端连接的数量;属性Socket.Connections[Index] 则用于访问单个与ClientSocket连接的Socket。

    正是这样的结构,才使得WinSocket 技术能够稳定实现一个服务程序向多个客户端提供服务。

    在独立的ClientSocket中,属性Socket.Data 是一个指针,缺省值是nil ;在ServerSocket的每个独立的Socket.Connections[Index]中, 属性Data也是一个指针,缺省值是nil 。因此,可以通过该指针建立并保存各自独立的相关信息,用于实现各自独立的通信。而在ClientSocket的事件 OnRead中,调用方法传递的Socket值就是响应该事件的对象属性ClientSocket.Socket 。同样,在 ServerSocket的事件OnClientRead中,调用方法传递的参数Socket就是对应于当前发送数据客户端的唯一的Socket连接,即ServerSocket.Socket.Connections[Index]。这样,就能够对不同的连接分得清清楚楚明明白白。

    首先介绍实例程序的设计思想。上传文件的过程是这样的(这里的C和S分别代表客户端和服务器端):

    C:请求上传文件;
    S:准备就绪,可以接收;
    C:需要上传的文件信息;
    S:收到文件信息:
    C:第一个包;
    S:收到第一个包;创建文件,开始写数据;
    C:中间的包;
    S:收到中间的包;继续写数据;
    C:发送最后一个包,关闭文件;
    S:收到最后一个包;写数据,关闭文件。
    下载文件的过程是这样的:

    C:请求下载文件;
    S:准备就绪,可以下载;
    C:需要下载的文件信息(文件名);
    S:反馈文件信息(文件大小);
    C:准备就绪,可以接收数据;
    S:第一个包;
    C:收到第一个包;创建文件,开始写数据;
    S:中间的包;
    C:收到中间的包;继续写数据;
    S:发送最后一个包,关闭文件;
    C:收到最后一个包;写数据,关闭文件;下载成功;
    S:下载成功。

    其中,发送中间的包和收到中间的包根据包的数量可以重复。不难看出,上面的两个过程是典型的“你一句我一句”的应答方式。

    下面是客户端应用程序和服务器端应用程序的结构。客户端应用程序包括:

    Client.DPR
    uClient.PAS(.DFM)(一个ClientSocket组件、一个按钮、一个标签、一个进度条)
    uClientMain.PAS(.DFM)(用于选择文件的一组控件和一个Edit控件、三个按钮)
    uSocketCommon.PAS
    服务器端应用程序包括:

    Server.DPR
    uServer.PAS(.DFM)(一个ServerSocket组件、一个Memo控件、两个按钮)
    uSocketCommon.PAS
    其中,单元uSocketCommon 中包括了Socket编程的主要代码,是客户端应用程序和服务器端应用程序都需要的。

    结合本例,可以对Delphi中的WinSocket编程作如下总结:

    数据收发是通过会话建立和撤消的;
    客户端是主动连接,服务程序是被动连接;
    每次收发的数据包,其容量是有限的,应当在设计时充分考虑;
    一个ClientSocket只能建立一个与ServerSocket的连接;
    一个ServerSocket可以建立多个与ClientSocket的连接;
    每一对连接都有唯一用于该连接的一对(两个)Socket,可以通过Data属性进行标记区分;
    不要对无效的数据包进行响应,否则可能会导致服务程序死锁;
    可以在传送的包中包含身份验证信息以确认是有效的数据。



  • 相关阅读:
    Preserving Remote IP/Host while proxying
    使用EF Core生成实体类 用来作为NetCore数据库访问上下文 Context
    【ASP.NET Core快速入门】(八)Middleware管道介绍、自己动手构建RequestDelegate管道
    NetCore WebApi 基于Jwt的验证授权方式
    Net Core 页面的生命周期 + OnActionExecuting
    C# 多线程发送邮件 代码版
    ASP.NET Core 中的过滤器(Action过滤器,控制器过滤器,全局应用程序过滤器)
    深入理解 NetCore 中的依赖注入的好处 及 、Singleton、Scoped、Transient 三种对象的差异
    巧用 display: contents 增强页面语义
    巧妙实现带圆角的渐变边框
  • 原文地址:https://www.cnblogs.com/zhangzhifeng/p/3254540.html
Copyright © 2011-2022 走看看