首页 > 编程知识 正文

超越函数怎么解,基本超越函数

时间:2023-05-03 17:55:21 阅读:62746 作者:996

接受连接请求

服务器最常见的事情之一是接受客户端的连接请求。 套接字上使用重叠I/O接受连接的唯一API是AcceptEx ()函数。 有趣的是,常规同步接受函数accept ()的返回值是新套接字(AcceptEx ) ) )函数需要另一个套接字作为其参数之一。 这是因为AcceptEx ()是重复的操作,必须先创建套接字,然后通过参数将套接字传递给AcceptEx ) )。 以下是典型的AcceptEx ) )的伪代码的一部分。

o{-等待最后一个AcceptEx完成-创建新套接字并将其与完成端口关联-设置背景结构等-发出AcceptEx请求} while (真);

作为响应性较高的服务,必须发出足够的AcceptEx调用进行等待,以便在客户端连接请求发生时立即响应。 至于发布多少个AcceptEx才足够,取决于服务器程序期望的通信交通类型。 例如,在进入连接率高的状况时(由于连接时间短,或者交通工具发生可怕的密钥时),需要等待AcceptEx当然比偶然进入的客户端连接时多。 聪明的方法是分析交通状况,并调整AcceptEx等待的次数,而不是将交通状况固定为特定的数量。

在Windows2000上,Winsock提供了一种用于确定AcceptEx数量是否足够的机制。 这是在创建监听套接字时创建事件,并通过名为WSAEventSelect (的API注册FD_ACCEPT事件通知来将套接字与其相关联。 如果系统接收到连接请求后,系统上没有AcceptEx ()等待接受连接,则上述事件将接收信号。 通过此事件,您可以确定是否发出了足够的AcceptEx (),或者是否检测到了异常的客户请求)。 此机制不适用于Windows NT 4.0。

x; background-color:rgb(250,247,239)"> 使用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()直接从底层的提供者那里取得函数的指针。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。