Delphi Socket 阻塞线程下为什么不触发OnRead和OnWrite事件
//**********************************************************************************
//说明: 阻塞线程下为什么不触发OnRead和OnWrite事件
//作者: licwing 时间: 2001-5-18
//Email: rurality@21cn.com
//**********************************************************************************
1.首先先分析TServerSocket的继承关系
TAbstractSocket->TCustomSocket->TCustomServerSocket->TServerSocket
属性 ServerType 是在 TCustomServerSocket 里面定义的
property ServerType: TServerType read GetServerType write SetServerType;
同时在TCustomServerSocket里定义了TServerWinSocket,用来处理客户连接
TServerWinSocket的继承关系如下:
TCustomWinSocket->TServerWinSocket
也就是说我们在TServerSocket里面触发的OnRead,OnWrite事件事实上是由TServerSocket
的父类TCustomServerSocket中的TServerWinSocket触发的。
2.现在我们分析在TCustomServerSocket里定义的TServerWinSocket客户连接方法
procedure TServerWinSocket.Accept(Socket: TSocket);
var
ClientSocket: TServerClientWinSocket;
ClientWinSocket: TSocket;
Addr: TSockAddrIn;
Len: Integer;
OldOpenType, NewOpenType: Integer;
begin
Len := SizeOf(OldOpenType);
if getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, PChar(@OldOpenType),
Len) = 0 then
//从这里开始是处理多线程的
try
if FServerType = stThreadBlocking then
begin
// SO_SYNCHRONOUS_NONALERT = $20 在winsock单元里面定义
//{$EXTERNALSYM SO_SYNCHRONOUS_NONALERT}
NewOpenType := SO_SYNCHRONOUS_NONALERT;
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, PChar(@NewOpenType), Len);
end;
Len := SizeOf(Addr);
ClientWinSocket := WinSock.accept(Socket, @Addr, @Len);
if ClientWinSocket <> INVALID_SOCKET then
begin
ClientSocket := GetClientSocket(ClientWinSocket);
if Assigned(FOnSocketEvent) then
FOnSocketEvent(Self, ClientSocket, seAccept);
if FServerType = stThreadBlocking then
begin
//********多线程事件响应关键部分*******
//TAsyncStyle = (asRead, asWrite, asOOB, asAccept, asConnect, asClose);
//asRead The socket receives notification that the connection is ready for reading.
//asWrite The socket receives notification that the connection is ready for writing.
ClientSocket.ASyncStyles := [];
//*************************************
GetServerThread(ClientSocket);
end;
end;
finally
Len := SizeOf(OldOpenType);
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, PChar(@OldOpenType), Len);
end;
end;
3.ASyncStyles属性只有在TCustomWinSocke类里面定义的,再看SetAsyncStyles过程
procedure TCustomWinSocket.DoSetAsyncStyles;
var
Msg: Integer;
Wnd: HWnd;
Blocking: Longint;
begin
Msg := 0;
Wnd := 0;
if FAsyncStyles <> [] then //非阻塞模式
begin
Msg := CM_SOCKETMESSAGE; //由消息CM_SOCKETMESSAGE触发的过程是过程
//TCustomWinSocket.CMSocketMessage(var Message: TCMSocketMessage);
Wnd := Handle;
end;
WSAAsyncSelect(FSocket, Wnd, Msg, Longint(Byte(FAsyncStyles))); //非阻塞模式处理
if FASyncStyles = [] then //阻塞模式
begin
Blocking := 0;
ioctlsocket(FSocket, FIONBIO, Blocking);//阻塞模式处理
end;
end;
4.再看由消息CM_SOCKETMESSAGE触发的过程
procedure TCustomWinSocket.CMSocketMessage(var Message: TCMSocketMessage);
begin
with Message do
if CheckError then
case SelectEvent of
FD_CONNECT: Connect(Socket);
FD_CLOSE: Disconnect(Socket);
FD_READ: Read(Socket); //触发Read事件
FD_WRITE: Write(Socket); //触发Write事件
FD_ACCEPT: Accept(Socket);
end;
end;
现在应该明白为什么在阻塞模式下不触发OnRead和OnWrite事件了吧?
Delphi Socket 阻塞线程下为什么不触发OnRead和OnWrite事件的更多相关文章
- delphi TServerSocket阻塞线程单元 实例
TServerSocket阻塞线程单元,希望对你有所帮助.需要注意的是:1.如果你使用TServerSocket的stNonBlocking模式,重写TServerClientThread线程时要重载 ...
- socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto
socket异步通信-如何设置成非阻塞模式.非阻塞模式下判断connect成功(失败).判断recv/recvfrom成功(失败).判断send/sendto 博客分类: Linux Socket s ...
- 关于socket阻塞与非阻塞情况下的recv、send、read、write返回值---部分内容可能不确切,待讨论
1.阻塞模式与非阻塞模式下recv的返回值各代表什么意思?有没有区别?(就我目前了解阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小,特别:返回值 ...
- 关于socket阻塞与非阻塞情况下的recv、send、read、write返回值(转载)
1.阻塞模式与非阻塞模式下recv的返回值各代表什么意思?有没有区别?(就我目前了解阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小,特别:返回值 ...
- UNIX网络编程——关于socket阻塞与非阻塞情况下的recv、send、read、write返回值
1.阻塞模式与非阻塞模式下recv的返回值各代表什么意思?有没有 区别?(就我目前了解阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小,特别:返回 ...
- Delphi Socket通信及多线程编程总结
http://cxhblog.blog.sohu.com/41930676.html 一.Socket通信: Delphi在ScktComp单元中对WinSock进行了封装,该单元提供了TAbstra ...
- socket阻塞与非阻塞,同步与异步、I/O模型,select与poll、epoll比较
1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步/异步主要针对C端: 同步: 所谓同步,就 ...
- socket阻塞与非阻塞,同步与异步
socket阻塞与非阻塞,同步与异步 作者:huangguisu 转自:http://blog.csdn.net/hguisu/article/details/7453390 1. 概念理解 在进行网 ...
- C#中的线程(下)-多线程
1. 单元模式和Windows Forms 单元模式线程是一个自动线程安全机制, 非常贴近于COM——Microsoft的遗留下的组件对象模型.尽管.NET最大地放弃摆脱了遗留下的模型,但很多时候它 ...
随机推荐
- USACO/friday
Friday the Thirteenth 黑色星期五 描述 13号又是一个星期五.13号在星期五比在其他日子少吗?为了回答这个问题,写一个程序,要求计算每个月的十三号落在周一到周日的次数.给出N年的 ...
- ASP.NET 3.5 中实现发送email电子邮件
来源:红黑联盟 方法1:cs代码 using System.Net.Mail; using System.Net; string mailServerName = "smtp.qq.com& ...
- SwitchyOmega
SwitchyOmega下载安装地址: http://switchyomega.com/download.html GFWList.bak.txt教程 {"+GFWed":{&qu ...
- RMAN备份与恢复之删除过期备份
使用crosscheck backupset或crosscheck backup之后,提示所有备份集都为available状态,当他执行delete obsolete时,提示有两个文件需要删除.实际上 ...
- eclipse解压后启动弹出A Java Runtime Evironment(JRE) or Java Development Kit(JDK)....
系统环境:win7 64bit JDK:jdk-7u79-windows-x64 Eclipse:eclipse-jee-helios-win32 启动eclipse:弹出A Java Runtime ...
- scala之method和function的区别
在我没有学习scala的时候,主要用java和python做日常工作开发,印象中,没有特别的刻意的去区分method和function的区别,这个关系,正如我们日常生活中,没有刻意的去区分质量和重量. ...
- [原]在Fedora中编译Libevent测试实例
在我的昨天的博文<[原]我在Windows环境下的首个Libevent测试实例>中介绍了在Windows环境下如何编译一个echo server例子.今天我又试了一下在Linux环境中编译 ...
- 清理SQL Server日志释放文件空间的终极方法
清理SQL Server日志释放文件空间的终极方法 转自:http://www.cnblogs.com/dudu/archive/2013/04/10/3011416.html [问题场景]有一个数 ...
- C#读取系统信息
using System; using System.Management; namespace Soyee.Comm { /// <summary> /// Computer Infor ...
- 【转】SQL SERVER 开窗函数简介
在SQL SERVER 2005/2008支持两种排名开窗函数和聚集开窗函数. 以SQL SERVER中分面页为例,按时间顺序列出定单号. WITH OrderInfo AS ( SELECT ROW ...