//**********************************************************************************
//说明: 阻塞线程下为什么不触发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事件的更多相关文章

  1. delphi TServerSocket阻塞线程单元 实例

    TServerSocket阻塞线程单元,希望对你有所帮助.需要注意的是:1.如果你使用TServerSocket的stNonBlocking模式,重写TServerClientThread线程时要重载 ...

  2. socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto

    socket异步通信-如何设置成非阻塞模式.非阻塞模式下判断connect成功(失败).判断recv/recvfrom成功(失败).判断send/sendto 博客分类: Linux Socket s ...

  3. 关于socket阻塞与非阻塞情况下的recv、send、read、write返回值---部分内容可能不确切,待讨论

    1.阻塞模式与非阻塞模式下recv的返回值各代表什么意思?有没有区别?(就我目前了解阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小,特别:返回值  ...

  4. 关于socket阻塞与非阻塞情况下的recv、send、read、write返回值(转载)

    1.阻塞模式与非阻塞模式下recv的返回值各代表什么意思?有没有区别?(就我目前了解阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小,特别:返回值  ...

  5. UNIX网络编程——关于socket阻塞与非阻塞情况下的recv、send、read、write返回值

    1.阻塞模式与非阻塞模式下recv的返回值各代表什么意思?有没有 区别?(就我目前了解阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小,特别:返回 ...

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

    http://cxhblog.blog.sohu.com/41930676.html 一.Socket通信: Delphi在ScktComp单元中对WinSock进行了封装,该单元提供了TAbstra ...

  7. socket阻塞与非阻塞,同步与异步、I/O模型,select与poll、epoll比较

    1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步/异步主要针对C端: 同步:      所谓同步,就 ...

  8. socket阻塞与非阻塞,同步与异步

    socket阻塞与非阻塞,同步与异步 作者:huangguisu 转自:http://blog.csdn.net/hguisu/article/details/7453390 1. 概念理解 在进行网 ...

  9. C#中的线程(下)-多线程

    1.  单元模式和Windows Forms 单元模式线程是一个自动线程安全机制, 非常贴近于COM——Microsoft的遗留下的组件对象模型.尽管.NET最大地放弃摆脱了遗留下的模型,但很多时候它 ...

随机推荐

  1. MySql远程连接无法打开解决办法

    1.改表法. 请使用mysql管理工具,如:SQLyog Enterprise 可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑使用mysql管理工 ...

  2. 【web】 亿级Web系统搭建——单机到分布式集群

      当一个Web系统从日访问量10万逐步增长到1000万,甚至超过1亿的过程中,Web系统承受的压力会越来越大,在这个过程中,我们会遇到很多的问题.为了解决这些性能压力带来问题,我们需要在Web系统架 ...

  3. VBA 按照文件类型名称打开一个文件

    Application.GetOpenFilename(fileFilter, fileIndex, fileSelectTitle, button, False) fileFilter: 指定能够被 ...

  4. C++资料大全

    本文内容源自GitHub<Awesome C/C++>. 关于 C++ 框架.库和资源的一些汇总列表,由 fffaraz 发起和维护. 内容包括:标准库.Web应用框架.人工智能.数据库. ...

  5. 【jmeter】关联-正则表达和xpath

    话说LoadRunner有的一些功能,比如:参数化.检查点.集合点.关联,Jmeter也都有这些功能,只是功能可能稍弱一些,今天就关联来讲解一下. JMeter的关联方法有两种:后置处理器-正则表达式 ...

  6. 【linux】find命令详解

    find命令格式:find [搜索范围][匹配条件] -name 参数:按照名字查找 [root@andon ~]# find /root -name test ###精确查找 /root/test ...

  7. 使用 OWIN 作为 ASP.NET Web API 的宿主

    使用 OWIN 作为 ASP.NET Web API 的宿主 ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动 设备)的 HTTP 服务. ASP.NET ...

  8. java-多态性

    1 多态性 主要表现在上转型对象 2 强制类型转换 2.1 基本类型的强制类型转换 转换只能在数值间进行.包括整数型.字符型.浮点型.数值类型和布尔类型间不能转换. 2.2 引用类型变量转换成其子类型 ...

  9. BOOST的AUTO link机制以及配置

    我们在使用BOOST的时候,如果需要链接一些库,是不用我们手动去链接的,归根结底还是boost的auto_link这个机制,在boost下的auto_link.hpp这个文件夹里面,基本可以看出要根据 ...

  10. python正则表达式的学习记录

    match和findall的区别以及有括号和无括号的区别 strvar = "hello\n\nworld" find_re = re.compile("hello[.| ...