Delphi Socket通信及多线程编程总结

http://cxhblog.blog.sohu.com/41930676.html

一、Socket通信:

Delphi在ScktComp单元中对WinSock进行了封装,该单元提供了TAbstractSocket、TClientSocket、TClientWinSocket、TCustomSocket、TCustomWinSocket、TCustomServerSocket 、TServerClientThread、TServerWinSocket、  TServerClientWinSocket、、TServerSocket、TWinSocketStream等相关的类。

它的继承关系为:

                  

TAbstractSocket类是所有Socket组件的基类。

TCustomWinSocket类是所有WinSock对象的基类。

TClientSocket类用于管理客户Socket连接。

TClientWinSocket类:客户Socket组件(TClientSocket)使用它来为客户应用管理WinSock API调用。

TServerSocket类为TCP/IP服务器管理服务器Socket连接。

TServerClientWinSocket类:服务器Socket组件(TServerSocket)使用它管理到一个客户Socket的WinSock API调用。

TServerWinSocket类:服务器Socket组件(TServerSocket)使用它为TCP/IP监听连接管理WinSock API调用。

TWinSocketStream类:在线程阻塞工作模式下提供到Socket连接的读写服务。

TServerClientThread类:用于为每一个到客户Socket的独立的连接创建一个线程。

要点

TServerWinSocket类用于管理服务器端的Socket,TClientWinSocket类用于管理客户端Socket。因为我们用控件的话,放置的控件是标准的Socket控件不能为Windows平台直接管理和使用,所以要用TServerWinSocket和TClientWinSocket来分别进行管理使其转变为WinSock以便Windows平台更好的控制和使用。

服务器端Socket使用TServerClientWinSocket管理一个到客户Socket的连接。TServerClientWinSocket与TServerWinSocket的区别是:当把一个TServerSocket组件放置到一个窗体或数据模块上并进入监听状态后,就自动创建了TServerWinSocket,而只有当服务器Socket监听到一个客户Socket的连接请求时并接受了请求后,才创建一个TServerClientWinSocket。当客户Socket的连接断开时,自动删除相应的TServerClientWinSocket。TServerClientWinSocket有一个ServerWinSokcet属性,它返回处监听状态的服务器端Socket对象(TServerWinSocket)。

当你把服务端设置成stthreadblocking的阻塞方式的时候,OnRead根本不会被触发,OnRead是在非阻塞的异步的时候才会被触发.正确的方法(阻塞)是定义一个ClientThread的线程类,在ServerSocketGetThread的时候创建一个线程,处理客户端请求..这样就可以支持多个客户端同时连接和收发封包. 至于客户端,用非阻塞的方式就可以了.

疑问:

      1、ClientSocket的ClientType为ctNonBlocking ctBlocking的区别?
      2、ServerSocket的ServerType为stNonBlocking,stThreadBlocking的区别?

解答:

     1、ctNonBlocking(非阻塞):它是异步进行读写操作,因此数据的传输不会阻塞应用程序中其他的代码执行,使用非阻断型连接时,当连接的另一端试图读写信息时,会触发OnReceive和OnSend事件来通知你的Socket,从Socket连接中读取信息需要调用ReceiveBuf或ReceiveIn方法,写信息需要调用SendBuf,SendStream或SendIn方法。当连接阻断后,Socket必须主动在已建立的连接上读写信息,而不是被动地等待Socket连接来通知。如果想控制何时开始读或写,请使用阻断型Socket。它是处理机制是通过消息处理。ctBlocking(阻断):此为阻断式。

2、对于服务器端Socket,将BlockMode属性设置为bmBlocking或是bmThreadBlocking都可以建立阻断型连接。当Socket正在等待完成某个请求的读写操作时,阻断型连接会拦截住所有其他代码的执行。当属性是stThreadBlocking(线程阻塞模式)时,服务器端Socket组件总会为每一个客户端连接生成一个新的执行线程。当属性为bmBlocking时,程序被阻塞,直到一个新的连接建立。要在OngetThread中生成TServerClientThread来处理数据,这时ThreadCacheSize提供了一个线程池的功能。

二、多线程编程:

Delphi的VCL有一个缺陷,就是不支持多个线程同时访问它。如果线程中要访问VCL对象可以用Synchronize来实现,它用Method参数指定的方法去访问VCL对象,实际上线程本人并不调用这个方法,而是通知主线程调用这个方法,主线程一次只能收到一个通知,这样就避免了对VCL对象并发访问。(注:任何继承VCL中定义的类的对象就是VCL对象)

编写线程代码时,必须要考虑其他线程的影响,具体的说:一方面线程互斥,另一方面就是线程同步。互斥就是要解决多线程同时访问一个全局变量,同步就是解决线程执行顺序的问题(一个线程结束之后,自动唤醒等待它的运算结果的其它线程)。

线程互斥:要避免多个线程并发访问全局变量时发生冲突,VCL中提供了三种解决方法:锁定对象、设置临界段、共享读—独占写。

1、锁定对象:一些对象本身就有Lock和UnLock方法,线程在操作这类对象时可以用这两个方法,还有一些线程安全的对象,如TCanvas和TThreadlist,它们自身就有一种机制来保持线程安全,如TCanvas可以自动使用Lock和Unlock来锁定和解锁。

2、设置临界段:如果没Lock方法,可以考虑临界段,它象一个门,同一时刻内只允许一个线程访问。它是通过创建一个TCriticalSection的全局实例来实现的。它有两个方法:Acquire(锁定)和Release(开放)。注意,只有所有线程都是通过临界段访问与之相连的全局内存,这种方法才能起作用。

3、共享读—独占写:设置临界体段的方法有一个缺点,就是在同一时刻只能有一个线程访问全局变量,而实际上我们不是总是改全局变量,很多情况只是读,这并不对内存造成错误,这种情况我们可采用TMultiReadExclusiveWriteSynchronizer对象来实现多个线程同时读全局变量,而只允许一个线程改。与设置临界段相同的是,也要求所有访问都采用这个对象,它有如下方法:BeginRead,EndRead,BeginWrite及EndWrite。

线程同步:如果一个线程必须等到其他线程的任务结束才能够继续,那么可以通知它暂时挂起。具有两种方式:

1、  等待其他线程结束,调用WaitFor方法可以实现。

2、  等待一个作业完成,有时希望等待一个线程完成一些操作,而不是等待一个线程执行结束。如果是这样,则需要一个事件对象TEvent,事件对象必须为全局对象,它对所有的线程都是可见的。当一个线程完成了其他线程所要求的任务,它就调用TEvent.SetEvent方法打开一个标志,其他线程可以检查这个标志,从而得知需要的任务已经完成。如果要关掉这个标志,则应调用ResetEvent方法。

疑问:

线程局部变量与普通变量的区别?threadvar

答:线程的局部变量要想被线程中调用的函数来访问,就要用threadvar来声明这个变量,否则线程中调用的外部函数就不能访问这个变量,这类变量只能被线程内的函数来访问.

时间: 2024-10-21 06:52:17

Delphi Socket通信及多线程编程总结的相关文章

Java Socket 通信之多线程

一.简单的客户端与服务器交互(客户端向服务器发送数据,服务器将数据再返回给客户端) 服务端 * 1.创建服务器 指定端口 ServerSocket(int port) * 2.接收客户端连接 阻塞时 * 3.发送数据 * 接收多个客户端 Mulityserver.java package cn.Tcp; /* * 服务端 * 1.创建服务器 指定端口 ServerSocket(int port) * 2.接收客户端连接 阻塞时 * 3.发送数据 * 接收多个客户端 */ import java.

Delphi 实现多线程编程的线程类 TThread

http://blog.csdn.net/henreash/article/details/3183119 Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到, 但基本上都是对TThread类的几个成员作一简单介绍,再说明一下Execute的实现和Synchronize的用法就完了. 然而这并不是多线程编程的全部,我写此文的目的在于对此作一个补充. 线程本质上是进程中一段并发运行的代码. 一个进程至少有一个线程,即所谓的主线程. 同时还可以有多个

Delphi中线程类TThread 实现多线程编程

作者:Rogee出处:Http://Rogee.cnblogs.com/心得:BLOG是什么,它是一个记录学习过程的东西 Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对TThread类的几个成员作一简单介绍,再说明一下Execute的实现和Synchronize的用法就完了.然而这并不是多线程编程的全部,我写此文的目的在于对此作一个补充. 线程本质上是进程中一段并发运行的代码.一个进程至少有一个线程,即所谓的主线程.同时还可以

java网络编程Socket通信详解

Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket.像大家熟悉的QQ.MSN都使用了Socket相关的技术.下面就让我们一起揭开Socket的神秘面纱. Socket编程 一.网络基础知识(参考计算机网络)            关于计算机网络部分可以参考相关博客:           <TCP/IP协议栈及OSI参考模型详解> http://wangdy.blog.51cto.com/3845563/

linux系统socket通信编程实践

简单介绍并实现了基于UDP(TCP)的windows(UNIX下流程基本一致)下的服务端和客户端的程序,本文继续探讨关于UDP编程的一些细节. 下图是一个简单的UDP客户/服务器模型: .imageplus-append-lu-img-txt { overflow: hidden; margin: 10px 0 } .imageplus-append-nova-txt { border: 1px solid #f2f2f2; font-family: Microsoft YaHei; line-

VC++多线程编程-线程间的通信和线程同步

引用:http://blog.csdn.net/zjc0888/article/details/7372258 线程间通讯 一般而言,应用程序中的一个次要线程总是为主线程执行特定的任务,这样,主线程和次要线程间必定有一个信息传递的渠道,也就是主线程和次要线程间要进行通信.这种线程间的通信不但是难以避免的,而且在多线程编程中也是复杂和频繁的,下面将进行说明. 使用全局变量进行通信 由于属于同一个进程的各个线程共享操作系统分配该进程的资源,故解决线程间通信最简单的一种方法是使用全局变量.对于标准类型

DELPHI下多线程编程的几个思维误区(QDAC)

有几个网友私下问我一些有关线程的事情.过节写个东西上来大家交流. 思维误区1,自己新建的THREAD是线程,自己的主程序不是线程. 很多人在多线程编程没有把主线程也当作线程.其实主线程也是线程.看起来是废话,这个话确实很重要,这个就意味着,在DELPHI中,不光你开的线程,还有你的主线程所有的内存分配也是串的,进锁排队的.主线程和线程的区别 A.一般来说主线程的优先级高了点.(当然你也可以自己设置) B.主线程在WIN下是处理APPLICATION的消息. 其他基本与你自建线程无区别. 所以这一

C#socket通信-----多线程

我在之前的socket通信的基础上做了一点改进,使用多线程来使用,程序更加简洁实用.不足之处请指教哦! 话不多说,之前的随笔也有介绍,直接上代码啦! 服务端socket(serverSocket): 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Net; 7 us

vc 基于对话框多线程编程实例——线程之间的通信

 vc基于对话框多线程编程实例--线程之间的通信 实例: vc 基于对话框多线程编程实例--线程之间的通信,码迷,mamicode.com