有关谷歌浏览器的一个问题

先看我的测试结果:
最最low的服务器:
功能:监听新用户
   监听注册描述符的EPOLLIN和EPOLLOUT。
   触发EPOLLIN的话,打印缓冲区
   触发EPOLLOUT,发送固定字符串
代码:

/*************************************************************************
    > File Name: 1.cpp
    > Author: 朱紫钰
    > Mail: zhuziyu1157817544@gmail.com
    > Created Time: 2017年08月01日 星期二 12时54分24秒
 ************************************************************************/

#include<iostream>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/epoll.h>
#include<errno.h>
#include<stdio.h>
#include"server_epoll.h"
#define server_port 20000
using namespace std;

int main(int argc,char *argv[])
{
    struct sockaddr_in address;
    bzero(&address,sizeof(address));
    address.sin_family = AF_INET;
    address.sin_port = htons(server_port);
    address.sin_addr.s_addr = htonl(INADDR_ANY);

    epoll_class epoll_object(5);
    //int epollfd = epoll_create(5);
    //struct epoll_event events[65535];

    int listenfd = socket(PF_INET,SOCK_STREAM,0);
    bind(listenfd,(struct sockaddr*)&address,sizeof(address));
    listen(listenfd,5);

    epoll_object.server_addfd(listenfd);

    while(1){
        int ret = epoll_object.server_epoll_wait();

        if((ret < 0) && (errno != EINTR)){
            perror("errno : ");
            break;
        }
        cout << "ret = " << ret << endl;
        for(int i = 0;i < ret;i++){
            int sockfd = epoll_object.events[i].data.fd;
            if( listenfd == sockfd){
                cout << "有新客户连接了!" << endl;
                struct sockaddr_in client_address;
                socklen_t client_length = sizeof(client_address);
                int connfd = accept(listenfd,(struct sockaddr*)&client_address,&client_length);
                cout << "所创建的客户套接字是: "<< connfd << endl;
                if(connfd < 0) {
                    perror("errno : ");
                    continue;
                }
                epoll_object.server_addfd(connfd);
                continue;
            }
            else if(epoll_object.events[i].events & EPOLLIN){
                char buf[4096];
                memset(buf,0,4096);
                int ret2 = recv(sockfd,buf,4095,0);

                if(ret2 == 0){
                    close(sockfd);
                    printf("套接字为%d的客户端要关闭了!\n",sockfd);
                    epoll_object.server_delfd(sockfd);
                    continue;
                }
                cout << "buf :" << buf << endl;
                cout << "以上就是来自套接字" << sockfd << "发来的信息,处理信息中..." << endl;
                epoll_object.server_modfd(sockfd,EPOLLOUT);
                cout << "可以向描述符是"<< sockfd << "的客户端发送数据"<< endl;
            }
            else if(epoll_object.events[i].events & EPOLLOUT){
                cout << "已经触发写事件,正在写入请稍候..." << endl;
                char buf[4096];
                char buf2[65535];
                char readbuf[4096];
                int filefd = open("../servermanage/index.html",O_RDONLY);
                read(filefd,readbuf,4096);

                strcpy(buf2,readbuf);
                memset(buf,0,4096);
                strcat(buf,"HTTP/1.1 200 OK\r\n");
                strcat(buf,"Host: 127.0.0.1\r\n");
                strcat(buf,"Connection: keep-alive\r\n\n");
                //strcat(buf,buf2);
                send(sockfd,buf,strlen(buf),0);
                cout << "写入成功!\n" << endl;
                cout << endl << endl;
               epoll_object.server_modfd(sockfd,EPOLLIN);
            } 
        }
    }

}

再看最low的客户端:
功能:
   主线程和服务器三次握手建立连接,主线程和子线程都往相同的connfd中send和recv,且是阻塞型。
代码:

/*************************************************************************
    > File Name: 1.c
    > Author: 朱紫钰
    > Mail: zhuziyu1157817544@gmail.com
    > Created Time: 2017年08月03日 星期四 15时22分28秒
 ************************************************************************/

#include<stdio.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/types.h>
#include<sys/socket.h>
void *pthread_work(void* sockfd)
{
    int connfd = *(int*)sockfd;
    while(1){

        send(connfd,"这是来自客户端子线程请求",64,0);
        sleep(1);
        char buf[1024] = {0};
        recv(connfd,buf,1024,0);
        printf("这是客户端%d的子线程接收到的请求!\n",connfd);
        printf("%s\n\n",buf);
        sleep(4);
    }
}
int main()
{
    struct sockaddr_in client_address;
    client_address.sin_family = AF_INET;
    client_address.sin_port = htons(20000);
    inet_aton("127.0.0.1",&client_address.sin_addr);

    int connfd = socket(AF_INET,SOCK_STREAM,0);
    connect(connfd,(struct sockaddr*)&client_address,sizeof(client_address));

    pthread_t pthread;
    pthread_create(&pthread,NULL,(void*)pthread_work,(void*)&connfd);
    while(1){
        send(connfd,"这是来自客户端的消息\n",32,0);
        sleep(1);
        char buf[1024] = {0};
        recv(connfd,buf,1024,0);
        printf("这是客户端%d受到的来自服务器的消息:",connfd);
        printf("%s\n\n",buf);
        sleep(4);
    }
    return 0;
}

运行结果和分析:
服务器结果:
这里写图片描述

可以看到,子线程和主线程共用sockfd = 5.这是因为我的客户端设置主线程子线程共用sockfd = 5。

客户端结果:

这里写图片描述

以上是客户端接收到的结果。

这只是我用自己写的客户端测试了我自己写的low服务器,根据结果,发现一旦建立客户端和服务器建立了链接,除非客户端自己关闭,否则,服务器不会主动从epoll去除这个套接字描述符。如果客户端不主动关闭,那么这个通信的道路仍然是完好可通信的!

那么,如果真正应用过程中,客户端变成高达上的浏览器会怎么样?

我们知道,谷歌一个标签开一个进程,以下是我让浏览器去请求我写的low服务器的运行结果。谷歌浏览器要根据服务器返回的index.html去请求后续资源。资源有:index.html , in.php , zhuziyu.html , 还有一系列图片。

原服务器代码中注释了 :
//strcat(buf,buf2);是为了给我写的客户端发送更为简单的内容进行测试。现在我把这个注释拿掉.
index.html代码:

<html>
<head>
<meta http-equiv = "Content-Type" content = "text/html ; charset = utf-8">
<style>
.block{

    text-align:center;
}
.size{
    font-size:24px;
    font-color:##660099;
}
body{
    background: url("http://127.0.0.1:20000/home/zhuziyu/server/servermanage/朝阳.jpg")
    no-repeat center bottom; background-size: cover; background-attachment:fixed;

}
</style>
</head>
<body class = "block">
<form action="in.php" method = "post">
Name:<br>
<input type="text" name="name" >
<br>
Password:<br>
<input type="password" name="password">
<br><br>
<input type="submit" value="Submit">
</form> 

<p  class = "size"><strong>If you submit right,you will get the secret!<strong></p>
</body>
</html>

in.php代码:

<?php
$name =  $_POST["name"];
$password =  $_POST["password"];
?>

<?php 
if($password == "123456"){
    header("Location: http://127.0.0.1/home/zhuziyu/server/servermanege/zhuziyu.html"); 
}
else{
    header("Location: http://127.0.0.1/home/zhuziyu/server/servermanege"); 
}


?>

zhuziyu.html代码:

<html>
<head>
<meta http-equiv = "Content-Type" content = "text/html ; charset = utf-8">
<title> secret </title>
<style>
body{
    background: url("http://127.0.0.1:20000/home/zhuziyu/server/servermanege/橙色.jpg")
    no-repeat center bottom; background-size: cover; background-attachment:fixed;
}
.day{
    text-align:center;
}
.pic1{

    width:200px;
    height:200px;
    position: absolute;
    top:100px;
    left:450px;
    background: url("http://127.0.0.1:20000/home/zhuziyu/server/servermanege/Butteri1.jpg");


}
.pic2{

    width:200px;
    height:200px; 
    position: absolute;
    top:100px;
    left:700px; 
    background: url("http://127.0.0.1:20000/home/zhuziyu/server/servermanege/butter.jpg");


}   
.pic3{

    width:200px;
    height:200px; 
    position: absolute;
    top:350px;
    left:450px; 
    background: url("http://127.0.0.1:20000/home/zhuziyu/server/servermanege/i.jpg");


}   
.pic4{

    width:200px;
    height:200px; 
    position: absolute;
    top:350px;
    left:700px; 
    background: url("http://127.0.0.1/home:20000/zhuziyu/server/servermanege/butteri2.jpg");


}   
.text{
text-align:center;
}
</style>
</head>
<body>
<div class  = "text" style= "FONT-SIZE: 26pt; FILTER: wave(add=0,lightstrength=50,strength=3,freq=2,phrase=10); WIDTH: 100%; COLOR: #CC3300; LINE-HEIGHT: 100%; FONT-FAMILY: 华文行楷" ><strong>Hope Butter and Laura are together forever!Everyday is made of happiness!</strong></div>
<div class = "pic1" ></div>
<div class = "pic2" ></div>
<div class = "pic3" ></div>
<div class = "pic4" ></div>

</body>
</html>

现在用浏览器充当客户端,我们来看结果:
结果1:
这里写图片描述

可以在终端下看到,连接的套接字描述符是5,请求的url是/,我默认服务器响应返回index.html。

结果2:
这里写图片描述
可以看到,相同的标签,因为原index.html包括了一个叫http://127.0.0.1:20000/home/zhuziyu/server/servermanage/橙色.jpg的资源,因此浏览器向服务器请求该资源。从图片终端下可以看到浏览器已经把请求该资源的http请求包发给了服务器。

但是

这个有关图片url的请求包竟然被当作了一个新的客户端处理,即套接字描述符是7。我测试过,如果有很多url请求包,每一个url都包含一个要申请的资源,那么服务器都会把它当作新的客户端处理,也就是说,当一个index.html包含了多个url需要向服务器请求资源时候,有多少个资源请求,则在服务器对应多少各用户套接字描述符,如果在大胆猜测一下,那就是这个标签开了多个线程,每一个线程负责请求一个资源。

而且

看第三张图片:
这里写图片描述
当我关闭这个标签时候,才会显示套接字5和7关闭了.也就是说,我打开一个标签,标签内部,大胆猜测一下昂,至少是线程级别,一个线程维护一个资源请求和响应的通路。因此,我认为一个线程会创建一个套接字,然后就有很多的套接字,不同的套接字来合作对应同一个标签界面的组合搭建。又或许,多个线程请求的资源通过通信的方式,被同一个线程组合起来,最终构成了我们看到的界面,里面有php , css , jpg , png 等等。

而我之前写的那个很low的客户端,表明主线程和子线程可以共用一个套接字,因此,我认为,是浏览器自己的选择,导致一个标签创建了很多套接字,我认为我的服务器中有关epoll的系统调用正确。

但是说了这么半天,我觉得我需要用命令去验证这个想法。
 pstree -p 指定进程 :查看指定进程的线程
 
于是我运行我的服务器,还有谷歌浏览器(只打开了127.0.0.1:20000这一个标签页)。经验证,30646和30661中30661是标签:
30661下面是多线程的。
 这里写图片描述

但是我没有办法验证验证,在这30661下的线程中,有多个线程共同合作完成同一个标签界面的组合。悲伤…

有一解答,感觉解了我一半的问题,但是线程之间的工作问题,还不清楚:
http://www.ha97.com/2908.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值