goahead如何处理回调时间长的连续请求

我一直有一个疑惑,当界面发送一个请求,在这个请求完成之前,再次点击界面,会发生什么?是会将上一个请求打断直接开始执行新的请求,还是会按顺序执行两个请求,还是说第二次请求会被忽略掉?
所以我添加了一些打印,来验证问题的答案。
(1)我定义了一个action,用来返回一句文字,记录点击的次数。在其中增加了5秒的延时。

//在MAIN中添加:
    websDefineAction("quicklyClick", actionQuicklyClick);
//定义回调函数
static void actionQuicklyClick(Webs *wp)
{
    static int i = 0;
    i++;
    printf("[%s]start to sleep\n", __func__);
    sleep(5);
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp);
	websWrite(wp, "这是第%d次点击\n", i);
    websFlush(wp, 0);
	websDone(wp);
    printf("[%s]finish callback\n", __func__);
}

(2)创建一个界面,包含一个按钮和一个文字区域。点击按钮发送请求,并将收到的文字显示在文字区域内。

<!DOCTYPE html>
<html>
    <head>

    </head>
    <body>
        <script>
            function update()
            {
                var xmlhttp1;
                if (window.XMLHttpRequest) {
                    // code for IE7+, Firefox, Chrome, Opera, Safari
                    xmlhttp1=new XMLHttpRequest();
                } else {
                    // code for IE6, IE5
                    xmlhttp1=new ActiveXObject("Microsoft.XMLHTTP");
                }
                xmlhttp1.onreadystatechange=function() {
                    if (xmlhttp1.readyState==4 && xmlhttp1.status==200) {
                        var textareaContext = document.getElementsByTagName("textarea");
                        textareaContext[0].value += xmlhttp1.responseText;
                    }
                };
                xmlhttp1.open("GET","/action/quicklyClick",true);
                xmlhttp1.send();
            }
        </script>
        <button onclick="update();">click</button>
        <textarea></textarea>
    </body>
</html>

这里没有写head,写的不太规范,能运行就好。
(3)在goahead的源码关键位置增加打印。
在这里插入图片描述
在这里插入图片描述
(4)在js函数增加打印

 function update()
            {
                console.log("enter function at " + Date());
                var xmlhttp1;
                if (window.XMLHttpRequest) {
                    // code for IE7+, Firefox, Chrome, Opera, Safari
                    xmlhttp1=new XMLHttpRequest();
                } else {
                    // code for IE6, IE5
                    xmlhttp1=new ActiveXObject("Microsoft.XMLHTTP");
                }
                xmlhttp1.onreadystatechange=function() {
                    if(xmlhttp1.readyState==1) {
                        console.log("send request at " + Date());
                    }
                    if (xmlhttp1.readyState==4 && xmlhttp1.status==200) {
                        var textareaContext = document.getElementsByTagName("textarea");
                        textareaContext[0].value += xmlhttp1.responseText;
                    }
                };
                xmlhttp1.open("GET","/action/quicklyClick",true);
                xmlhttp1.send();
            }

(5)编译运行程序,打开界面后,连续点击三次按钮,观察界面和打印的结果。
(6)界面为每5秒增加一行显示,没有请求丢失。
在这里插入图片描述

(7)查看浏览器控制台打印

在这里插入图片描述
网页就是连续发送的,没有做什么处理。
我后续多开了一个窗口,新窗口点三下,旧窗口再点三下,还是按顺序执行的。
在这里插入图片描述
在这里插入图片描述
(8)控制台打印情况为
在这里插入图片描述
在这里插入图片描述
这里就很令人迷惑了,连续点击的三次,被轮流执行,但是第一次跟后两次情况又有所不同。
现在将可读情况区分为connection和action已经是不太合适的了,应该说成监听socket上捕获到的读事件和其他socket上捕捉到的socket事件。我们来看goahead对于这两种事件的处理:

typedef struct WebsSocket {
    WebsBuf         lineBuf;            /**< Line ring queue */
    SocketAccept    accept;             /**< Accept handler */
    SocketHandler   handler;            /**< User I/O handler */
    char            *ip;                /**< Server listen address or remote client address */
    void            *handler_data;      /**< User handler data */
    int             handlerMask;        /**< Handler events of interest */
    int             sid;                /**< Index into socket[] */
    int             port;               /**< Port to listen on */
    int             flags;              /**< Current state flags */
    Socket          sock;               /**< Actual socket handle */
    int             fileHandle;         /**< ID of the file handler */
    int             interestEvents;     /**< Mask of events to watch for */
    int             currentEvents;      /**< Mask of ready events (FD_xx) */
    int             selectEvents;       /**< Events being selected */
    int             saveMask;           /**< saved Mask for socketFlush */
    int             error;              /**< Last error */
    int             secure;             /**< Socket is using SSL */
    int             handshakes;         /**< Number of renegotiations */
} WebsSocket;

一个是调用socketAccept重新创建一个webSocket结构体,并且绑定websAccpet作为accept这一项结构体元素,之后执行accept。
一个是直接执行结构体中的handler元素。
这两者看似是不一样的,但其实不管是accept还是handler,内部执行的子函数其实都是socketEvent,不信你看:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
所以就是不管是否是负责监听的socket收到的可读事件,最后都是能被正确执行的。
但是这个不是问题的重点,重点是为什么我的三次点击是5s内连续的,但是服务端的接收却是依次的,我本来预想的是,会不会第一次anction执行完后,第二次可以直接读取到后两下的结果,然后进行消息拆分。但根据打印发现并非如此。
真实的情况是,我的点击事件是每次都创建一个http请求,都会发到监听端口,select捕捉到后,由accept取出一个,创建新的套接字进行处理。
在这里插入图片描述
在一开始设置监听端口的最大连接数是128。所以最多可以接收128个可能的连接,accept每次取出一个,进行处理,所以在回调之前多次点击,只要不超过128下,就可以按顺序执行。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值