用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属性进行标记区分;
不要对无效的数据包进行响应,否则可能会导致服务程序死锁;
可以在传送的包中包含身份验证信息以确认是有效的数据。


//

最新文章

  1. CSS常用渐变
  2. RichTextBoxEx
  3. eclipse将引用了第三方jar包的java项目打成jar包
  4. 解决git客户端MINGW32下的“Could not open a connection to your authentication agent.”
  5. Spring学习笔记—装配Bean
  6. jquery 日历插件datepicker格式调整
  7. JavaWeb基础: Tomcat
  8. json里的日期字符串 怎么 转换成 javascript 的 Date 对象?
  9. VC++ 2013 开发windows窗体程序
  10. DuKBitmapImages 图片压缩处理技术
  11. Qt对`vtable的未定义引用
  12. java 调用process
  13. MySQL 5.7 使用原生JSON类型
  14. jmeter 在linux服务器的安装和运行;
  15. Keepalived指定文件接收日志
  16. java操作Excel之POI(4)利用POI实现数据的批量导出
  17. 因为修改linux selinux修改错误产生的问题及解决办法
  18. help()
  19. delphi从dll中调用图片资源
  20. 文字选中的js实现

热门文章

  1. (转)Spring读书笔记-----Spring核心机制:依赖注入
  2. javascript类继承系列三(对象伪装)
  3. ZOJ 1057 Undercut(简单模拟)
  4. Android中解析XML的方法
  5. c++builder调用vc的dll
  6. JavaScript学习总结【8】、面向对象编程
  7. php读取excel,以及php打包文件夹为zip文件
  8. js获取时间天数
  9. yii下多条件多表组合查询以及自写ajax分页
  10. WPF实现导航的几种方式