1引言
Windows Sockets规范以U.C. Berkeley大学BSD UNIX中流行的Socket接口为范例定义了一套Microsoft Windows下网络编程接口。它不仅包含了人们所熟悉的Berkeley Socket风格的库函数;也包含了一组针对Windows的扩展库函数,以使程序员能充分地利用Windows消息驱动机制进行编程。
Windows Sockets 规范本意在于提供给应用程序开发者一套简单的API,并让各家网络软件供应商共同遵守。此外,在一个特定版本Windows的基础上,Windows Sockets 也定义了一个二进制接口(ABI),以此来保证应用Windows Sockets API 的应用程序能够在任何网络软件供应商的符合Windows Sockets协议的实现上工作。因此这份规范定义了应用程序开发者能够使用,并且网络软件供应商能够实现的一套库函数调用和相关语义。我们可以使用WinSock在Internet上传输数据和交换信息,而且可以不需要关心网络连接的细节,因而很受网络编程程序员的欢迎。
2 Delphi中Socket的操作方式
Delphi分别使用TClientSocket元件和TServerSocket元件来操纵客户端 Socket和服务器段Socket的连接和通信。根据连接发起的方式以及本地 Socket要连接的目标,Socket之间的连接可以分为:客户端连接、监听连接以及服务器端连接。
(1)所谓客户端连接,是指由客户端的 Socket提出连接请求,要连接的目标是服务器端的Socket。为此,客户端的Socket首先要描述它要连接的服务器端Socket,主要是服务器端Socket的地址和端口号,然后再定位所要连接的服务器端Socket。找到以后,就向服务器端Socket请求连接。此时,服务器端的Socket未必正好处于准备好状态。不过,服务器端Socket会自动维护一个客户请求队列,通过这个队列的优先顺序,会在适当的时候通过请求响应的方式向客户端Socket发出"允许连接"(Accept)的信号,这样便在客户端和服务器端通过Sockets建立了连接!
(2)所谓监听连接,是指服务器端Socket并不定位具体的客户端Socket,而是处于等待连接状态,当服务器端 Socket监听到或者接收到客户端Socket的连接请求的时候,它就响应客户端Socket的请求建立一个新的Socket句柄并与客户端连接,而服务器端Socket继续处于监听状态,这样可以与多个客户端同时建立连接。
(3)所谓服务器端连接,是指当服务器端Socket接收到客户端Socket的连接请求后,就把服务器端Socket的描述发送给客户端。一旦客户端确认了此描述,就建立了连接!
3 线程控制的提出
一旦服务器与客户端建立了连接之后,就可以通过 Internet 传输数据和文件。但是在WinSock中存在两种传输模式"阻塞"和"非阻塞"的概念。
一般都采用非阻塞方式。在客户端,如果把 ClientType特性设置为ctNonBlocking,表示采用非阻塞方式进行连接。当服务器端 Socket试图进行读/写操作的时候,客户端 Socket就会得到通知,即OnRead或者OnWrite事件。
对于服务器端Socket来说,如果把ServerType特性设置为 StNonBlocking,表示采取非阻塞方式进行连接。当客户端 Socket试图进行读/写的时候,服务器端Socket就会得到通知,即OnClientRead或者OnClientWrite事件。
与非阻塞方式不同的是,在阻塞方式下没有诸如OnRead或者OnWrite等异步事件。Socket必须主动去读或者写数据。在读写操作完成之前,其他代码都无法执行,成为了纯粹的独占使用方式,整个应用程序将处于等待状态,大大降低应用程序的性能。
对于客户端Socket来说,如果把 ClientType特性设置为ctBlocking,表示采取阻塞方式进行连接,为了尽可能的减少阻塞方式的负面影响,可以把所有涉及到读写的操作放在一个单独的线程中,这样可以使其他的线程可以继续得到执行。
对于服务器端 Socket来说,如果把ServerType设置为stThreadBlocking,表示采取阻塞方式进行连接。Delphi 中将为每一个阻塞方式的连接自动分配一个新的线程,这样即使一个客户正在进行读写操作,其他的客户也不必等待。
4 在客户端使用多线程技术
在阻塞模式下,为了尽可能的减少阻塞方式的副作用,可以把所有的涉及到读写操作放在一个单独的线程种。为此,需要创建一个新的线程对象,然后重载它的Execute方法,在线程代码中,我们通过TWinSockStream对象来进行读写操作。
Procedure TClientThread.Execute;
Var sStream: TWinSockStream;
sBuffer: string;
Begin
//建一个TWinSocketStream对象实例,设置连接超时
SSteam: = TWinSockStream.Create (ClientSocket.Socket, 60000);
Try //获取和操作命令,直到连接断开或者线程终止
While (not Terminate) and (ClientSocket.Active) do
begin
try
GetNextRequest (sBuffer);
//将请求写回到Server
sStream.Write (sBuffer, Length (sBuffer) + 1);

Except
if not(Except Object is EAbort) then
//处理一些自定义的异常情况
Synchronize(HandleThreadException);
end;
end;
finally
sStream.Free;
end;
End;
5 在服务器端使用多线程技术
在服务器端,Delphi将自动为每一个阻塞方式的连接分配一个新的线程,并通过TServerClientThread来操纵每一个线程。所以不能通过对象库中的向导来创建线程对象,只能手工建立一个TServerClientThread的派生类,然后重载ClientExcute方法。Procedure TServerThread.ClientExcute;
Var sStream:TWinSocketStream;
sBuffer:array[0..9] of char
Begin
//获取和操作命令,直到连接断开或者线程终止
While (not Terminate) and (ClientSocket.Active) do
Begin
Try
sStream:= TWinSocketStream.Create(ClientSocket.Socket,60000);
try //填充SBuffer数组
FillChar(sBuffer,10,0);
//延迟时间60秒
If sStream.WaitForData(60000) then
Begin
If sStream.Read(sBuffer,10)=0 then
ClientSocket.Close;
……
End
Else ClientSocket.Close;
except
HandleException;
end;
Finally
sStream.Free;
end;
end;
End;
总结:通过客户端和服务器端的多线程控制,当我们需要对大信息量的数据处理的时候,尤为方便,而且能够很大程度上提高网络资源的利用率。目前我们正在研究通过线程控制来对数据库的查询进行优化处理以及数据发送问题!

关于WinSock编程的多线程控制的更多相关文章

  1. ATL是如何实现线程安全的引用计数和多线程控制的

    ATL是如何实现线程安全的引用计数和多线程控制的 正如标题所示,这是我经常被问到的一个问题,而每次我都从头开始给人说一次,其实说来过程理解起来的确有点复杂. 我们的每一个ATL Server Obje ...

  2. winsock编程select模型

    winsock编程select模型 网络服务端连接数量过多时,为每一个连接申请一个线程会让机器性能急剧下降(大多说是因为线程在用户态和内核态之间切换会占用大量的CPU时间片).为了解决多线程带来的性能 ...

  3. Delphi下的WinSock编程

    一.定址        要通过Winsock建立通信,必须了解如何利用指定的协议为工作站定址.Winsock 2引入了几个新的.与协议无关的函数,它们可和任何一个地址家族一起使用:但是大多数情况下,各 ...

  4. C# 多线程控制

    C# 多线程控制 通讯 和切换   一.多线程的概念  Windows是一个多任务的系统,如果你使用的是windows 2000及其以上版本,你可以通过任务管理器查看当前系统运行的程序和进程.什么是进 ...

  5. 网络编程之多线程——GIL全局解释器锁

    网络编程之多线程--GIL全局解释器锁 一.引子 定义: In CPython, the global interpreter lock, or GIL, is a mutex that preven ...

  6. Winsock编程原理——面向连接

    Winsock编程原理——面向连接 Windows Sockets使用套接字进行编程,套接字编程是面向客户端/服务器模型而设计的,因此系统中需要客户端和服务器两个不同类型的进程,根据连接类型的不同,对 ...

  7. Winsock 编程详解

    转载请注明出处!本文地址:https://www.cnblogs.com/teternity/p/WinSock.html Winsock 编程 目录 通用函数讲解 WSAStartup WSACle ...

  8. NetBIOS与Winsock编程接口

    最近在看网络编程方面的书,由于不是通信专业出身的,以前理解的网络体系感觉就是tcp/ip,最近工作上接触到了一些光环网等乱七八糟的东西,有些基本的LC.SC连接器都不认识.花时间看了下计算机网络体系结 ...

  9. C# winform编程中多线程操作控件方法

    private void Form1_Load(object sender, EventArgs e) { Thread newthread = new Thread(new ThreadStart( ...

随机推荐

  1. Axure无法签出,团队配合时无法导入项目

    SVN管理项目,团队多人合作维护 在Axure签出时,报错. 提示:无法创建目录 ... 设备上没有空间 SVN也检出失败 当然,还有其他情况 如:未将对象引用设置到对象的实例.等等 个别提示如下图: ...

  2. java开发工具STS的下载及安装

    将下载后的压缩文件解压,在解压后的sts-bundle下的sts-3.9.1RELEASE目录中STS.exe便是可执行程序,用于启动STS,将该文件发送到桌面快捷方式,当我们想使用STS时可以快速的 ...

  3. CImage的坑

    1.现象 在栈上定义CImage,加载本地图片,在界面上显示,报内存异常,访问失败 2.结论 图片过大,会是CImage产生这种问题 3.解决 把CImage定义到堆上,回收内存 new Load D ...

  4. Appium 框架工作流程及原理

    目前Appium框架可以时支持android 和 ios 两个操作系统的App自动化测试,咱们分别对以下两款操作系统的工作流程进行说明. 一.appium-Android工作流 在Android端,a ...

  5. Java构造器与构建器的使用

    我们在平常类的构建过程中,可能会面临很多问题,可扩张性.安全性等等.想象一下,这样一个场景,我们现在要创建一个类,其中有6个属性,其中又有4个属性的值是不太确定的(可能某个对象就不需要其中的某个值), ...

  6. UVA11107 Life Forms

    思路 后缀数组 先都拼在一起 二分+height分段 按照小于x的为分界,判断是否有一个分段中包含超过n/2个串 代码 #include <cstdio> #include <cst ...

  7. ASP.NET Core API 接收参数去掉烦人的 [FromBody]

    在测试ASP.NET Core API 项目的时候,发现后台接口参数为类型对象,对于PostMan和Ajax的Post方法传Json数据都获取不到相应的值,后来在类型参数前面加了一个[FromBody ...

  8. Unity日常记录 - QualitySettings 性能设置

    unity打包时,可通过QualitySettings优化图像性能,这是最常设置也是最明显的图像性能体现 设置图形质量的水平,一般来说,质量是以牺牲性能为代价的,所以最好不要追求移动设备或旧硬件的最高 ...

  9. POJ 3616 奶牛挤奶

    Milking Time 贝茜是一个勤劳的牛.事实上,她如此​​专注于最大化她的生产力,于是她决定安排下一个N(1≤N≤1,000,000)小时(方便地标记为0..N-1),以便她生产尽可能多的牛奶. ...

  10. 在action中进行文件下载,下载时运行不报错,可是也不下载

    在写前端下载页面时,使用ajax方式调用action中的方法,然后就将下载内容返回js中了,所以没有下载,之后改为使用Windows.location进行下载,就没有问题了. action中代码: i ...