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. dnsmasq 设置自动获取主机名

    A1_IP:192.168.164.145 A1# yum install dnsmasq -y A1# echo "addn-hosts=/etc/domains" >&g ...

  2. day11函数的参数,函数对象 - 函数名,函数的嵌套调用

    复习 # 什么是函数:具体特定功能的代码块 - 特定功能代码块作为一个整体,并给该整体命名,就是函数 # 函数的优点: # 1.减少代码的冗余 # 2.结构清晰,可读性强 # 3.具有复用性,开发效率 ...

  3. BZOJ-1721|线性dp-缆车支柱

    Ski Lift 缆车支柱 Description Farmer Ron in Colorado is building a ski resort for his cows (though budge ...

  4. java解压多层目录中多个压缩文件和处理压缩文件中有内层目录的情况

    代码: package com.xiaobai; import java.io.File; import java.io.FileOutputStream; import java.io.IOExce ...

  5. LintCode 846.多关键字排序

    LintCode 846.多关键字排序 描述 给定 n 个学生的学号(从 1 到 n 编号)以及他们的考试成绩,表示为(学号,考试成绩),请将这些学生按考试成绩降序排序,若考试成绩相同,则按学号升序排 ...

  6. 解决 Cannot uninstall 'pyparsing' 问题

    参考 pyparsing 无法卸载导致安装 matplotlib 出错 解决 Cannot uninstall 'pyparsing' 问题 在安装 pydot 时遇到依赖 pyparsing 无法更 ...

  7. webpack 4.X 基础编译

    webpack4.x的打包已经不能用webpack 文件a 文件b的方式,而是直接运行webpack --mode development或者webpack --mode production,这样便 ...

  8. Ubuntu - Start - 必要软件安装

    1.安装Chromium浏览器 sudo apt install chromium-browser 如果出错, 先更新下apt sudo apt update 2. 安装rime输入法 sudo ap ...

  9. 雷林鹏分享:jQuery EasyUI 数据网格 - 设置冻结列

    jQuery EasyUI 数据网格 - 设置冻结列 本实例演示如何冻结一些列,当用户在网格上移动水平滚动条时,冻结列不能滚动到视图的外部. 为了冻结列,您需要定义 frozenColumns 属性. ...

  10. English trip EM2-MP4 Teacher:Taylor voiceless consonant 清辅音 & voiced consonant 浊辅音

    课上内容(Lesson) # 区分 voiceless consonant 清辅音 & voiced consonant 浊辅音 清辅音    short   # 轻快 浊辅音    long ...