接受连接请求

服务器要做的最普通的事情之一就是接受来自客户端的连接请求。在套接字上使用重叠I/O接受连接的惟一API就是AcceptEx()函数。有趣的是,通常的同步接受函数accept()的返回值是一个新的套接字,而AcceptEx()函数则需要另外一个套接字作为它的参数之一。这是因为AcceptEx()是一个重叠操作,所以你需要事先创建一个套接字(但不要绑定或连接它),并把这个套接字通过参数传给AcceptEx()。以下是一小段典型的使用AcceptEx()的伪代码:

do {
    -等待上一个 AcceptEx 完成
    -创建一个新套接字并与完成端口进行关联
    -设置背景结构等等
    -发出一个 AcceptEx 请求
}while(TRUE);

作为一个高响应能力的服务器,它必须发出足够的AcceptEx调用,守候着,一旦出现客户端连接请求就立刻响应。至于发出多少个AcceptEx才够,就取决于你的服务器程序所期待的通信交通类型。比如,如果进入连接率高的情况(因为连接持续时间较短,或者出现交通高峰),那么所需要守候的AcceptEx当然要比那些偶尔进入的客户端连接的情况要多。聪明的做法是,由应用程序来分析交通状况,并调整AcceptEx守候的数量,而不是固定在某个数量上。

对于Windows2000,Winsock提供了一些机制,帮助你判定AcceptEx的数量是否足够。这就是,在创建监听套接字时创建一个事件,通过WSAEventSelect()这个API并注册FD_ACCEPT事件通知来把套接字和这个事件关联起来。一旦系统收到一个连接请求,如果系统中没有AcceptEx()正在等待接受连接,那么上面的事件将收到一个信号。通过这个事件,你就可以判断你有没有发出足够的AcceptEx(),或者检测出一个非正常的客户请求(下文述)。这种机制对Windows NT 4.0不适用。

使用AcceptEx()的一大好处是,你可以通过一次调用就完成接受客户端连接请求和接受数据(通过传送lpOutputBuffer参数)两件事情。也就是说,如果客户端在发出连接的同时传输数据,你的AcceptEx()调用在连接创建并接收了客户端数据后就可以立刻返回。这样可能是很有用的,但是也可能会引发问题,因为AcceptEx()必须等全部客户端数据都收到了才返回。具体来说,如果你在发出AcceptEx()调用的同时传递了lpOutputBuffer参数,那么AcceptEx()不再是一项原子型的操作,而是分成了两步:接受客户连接,等待接收数据。当缺少一种机制来通知你的应用程序所发生的这种情况:“连接已经建立了,正在等待客户端数据”,这将意味着有可能出现客户端只发出连接请求,但是不发送数据。如果你的服务器收到太多这种类型的连接时,它将拒绝连接更多的合法客户端请求。这就是黑客进行“拒绝服务”攻击的常见手法。

要预防此类攻击,接受连接的线程应该不时地通过调用getsockopt()函数(选项参数为SO_CONNECT_TIME)来检查AcceptEx()里守候的套接字。getsockopt()函数的选项值将被设置为套接字被连接的时间,或者设置为-1(代表套接字尚未建立连接)。这时,WSAEventSelect()的特性就可以很好地利用来做这种检查。如果发现连接已经建立,但是很久都没有收到数据的情况,那么就应该终止连接,方法就是关闭作为参数提供给AcceptEx()的那个套接字。注意,在多数非紧急情况下,如果套接字已经传递给AcceptEx()并开始守候,但还未建立连接,那么你的应用程序不应该关闭它们。这是因为即使关闭了这些套接字,出于提高系统性能的考虑,在连接进入之前,或者监听套接字自身被关闭之前,相应的内核模式的数据结构也不会被干净地清除。

发出AcceptEx()调用的线程,似乎与那个进行完成端口关联操作、处理其它I/O完成通知的线程是同一个,但是,别忘记线程里应该尽力避免执行阻塞型的操作。Winsock2分层结构的一个副作用是调用socket()或WSASocket() API的上层架构可能很重要(译者不太明白原文意思,抱歉)。每个AcceptEx()调用都需要创建一个新套接字,所以最好有一个独立的线程专门调用AcceptEx(),而不参与其它I/O处理。你也可以利用这个线程来执行其它任务,比如事件记录。

有关AcceptEx()的最后一个注意事项:要实现这些API,并不需要其它提供商提供的Winsock2实现。这一点对微软特有的其它API也同样适用,比如TransmitFile()和GetAcceptExSockAddrs(),以及其它可能会被加入到新版Windows的API. 在Windows NT和2000上,这些API是在微软的底层提供者DLL(mswsock.dll)中实现的,可通过与mswsock.lib编译连接进行调用,或者通过WSAIoctl() (选项参数为SIO_GET_EXTENSION_FUNCTION_POINTER)动态获得函数的指针。

如果在没有事先获得函数指针的情况下直接调用函数(也就是说,编译时静态连接mswsock.lib,在程序中直接调用函数),那么性能将很受影响。因为AcceptEx()被置于Winsock2架构之外,每次调用时它都被迫通过WSAIoctl()取得函数指针。要避免这种性能损失,需要使用这些API的应用程序应该通过调用WSAIoctl()直接从底层的提供者那里取得函数的指针。

AcceptEx函数特点及需要提防的地方,看完了解更深入了,所以转过来相关推荐

  1. lambda函数if_lambda表达式速度如何呢?看完这篇文章你就明白了

    虽然Java 8已经出了好几年了,但是很多朋友可能对于其中的一些特性还是不太了解.甚至对lambda表达式这个特性可能会产生误解,误认为lambda表达式会影响程序的速度.其中也不乏很多误人子弟的自媒 ...

  2. ln函数怎么看奇偶性_Python中函数的参数应该怎么理解?看完这篇文章情不自禁的想收藏...

    前面给大家讲过,函数是一种编程思想,是提高代码重复利用的设计思路,是代码设计更深层次的产物.今天要给大家讲的就是函数的核心:函数的参数 基本概念 1.函数的参数:是指函数完成某项功能所需要的信息. 举 ...

  3. AcceptEx函数的示例代码

    2. 关于AcceptEx 使用此函数时,要包含头文:Mswsock.h,同时要链接:Mswsock.lib.可在源程序中加入下面的语句,这样在编译时,将自动链接Mswsock.lib. #pragm ...

  4. 使用WSAIoctl获取AcceptEx函数指针

    Winsock2的其他供应商不一定会实现AcceptEx函数.同样情况也包括的其他Microsoft的特定APIs如TransmitFile,GetAcceptExSockAddrs以及其他Micro ...

  5. AcceptEx()函数详细解析

    服务器要做的最普通的事情之一就是接受来自客户端的连接请求.在套接字上使用重叠I/O接受连接的惟一API就是AcceptEx()函数[注一].有趣的是,通常的同步接受函数accept()的返回值是一个新 ...

  6. AcceptEx函数与完成端口的结合使用例子

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 这是在学 ...

  7. 关于AcceptEx函数

    AcceptEx函数的第一个参数listen_socket和第二个参数accept_sock不能相同. 并且第一个参数listen_socket必须开启监听,否则会返回10022错误. AcceptE ...

  8. 在别的地方看的给程序员介绍一些C++开源库,记录给大家共同学习

    在别的地方看的<<给程序员介绍一些C++开源库>>,记录给大家共同学习 首先说明这篇文章不是出自我手,大家共同学习. 引用地址:http://oss.org.cn/?actio ...

  9. 不想工作了怎么破?那就去这4个地方看一看

    微博上曾经有过这样一个征集:你现在最焦虑的问题是什么? 底下呼声最高的答案竟然是:不想工作了怎么破? 现代的成年人,越来越喜欢把"不想上班""想辞职"等话挂在嘴 ...

最新文章

  1. 一些关键字表明变量属性值
  2. 中科微研课题上犹授牌-农业大健康·李喜贵:谋定功能性农业
  3. python中常用的函数
  4. Fiori Error message Exception raised without specific error
  5. model存储 swift_Swift语言IOS8开发战记10.Data Model
  6. tensorboard ckpt pb 模型的输出节点_“技术需求”与“技术成果”项目之间关联度计算模型 TOP10 baseline...
  7. AssetManager asset的使用
  8. 第十章:在Spark集群上掌握比较重要的图操作之Computing Degree
  9. ps海报合成教程_PS教程:别不信,你也能合成游戏场景!
  10. android百度地图获取定位信息吗,android使用百度地圖定位(獲取當前經緯度和地址信息)...
  11. 不存在有效_文水2单位存在安全隐患!
  12. 《猎头局中局》作者萧东楼访谈摘录
  13. NTP实现联网校对时间详解
  14. 年轻人,你为什么要来阿里搞技术?
  15. HyperLynx(二十九)高速串行总线仿真(一)
  16. ubuntu16.04更新系统后桌面出错的解决办法
  17. 在 Python 中打印换行符——打印一个新行
  18. JAVA练习题——判断题
  19. ASM磁盘组添加ASM磁盘
  20. linux 7 iscsi 配置,RHEL7使用targetcli配置iSCSI

热门文章

  1. (转载)俞敏洪一分钟励志演讲
  2. NeXT,NEXTSTEP,OPENSTEP,Cocoa,Cocoa Touch,GNUstep,xcode
  3. css3之transform-origin属性详解图文笔记
  4. guava之限流RateLimiter
  5. python marshal loads failed_Python模块学习:marshal 对象的序列化
  6. 初中级前端程序员面试中小型公司会问哪些问题?
  7. iOS之导航UINavigationController的使用(一)
  8. 50个有趣的休闲网站 (外国)
  9. 嵌入式c语言如何在堆区开辟空间
  10. SOPHON BM1684芯片解码性能以及支持的文件格式