当前位置: 首页 > news >正文

手机网页代码黑帽seo

手机网页代码,黑帽seo,asp.net+制作网站开发,如何选择购物网站建设一.select 实现 (1)select流程 基本流程是: 1. 先构造一张有关文件描述符的表; fd_set readfds 2. 清空表 FD_ZERO() 3. 将你关心的文件描述符加入到这…

 

一.select 实现

(1)select流程

基本流程是:

1. 先构造一张有关文件描述符的表;                     fd_set readfds

2. 清空表                                                              FD_ZERO()

3. 将你关心的文件描述符加入到这个表中;           FD_SET()

4. 调用select函数。                                              selset()

5. 判断是哪一个或哪些文件描述符产生了事件(IO操作);   FD_ISSET()

6. 做对应的逻辑处理;       

(2)selset函数

头文件: #include<sys/select.h>   #include<sys/time.h>   

             #include<sys/types.h>   #include<unistd.h>

声明: int select(int nfds, fd_set *readfds, fd_set *writefds,\

                                    fd_set *exceptfds, struct timeval *timeout);

功能:监测是哪些文件描述符产生事件,阻塞等待产生.

参数:nfds:    监测的最大文件描述个数(文件描述符从0开始,这里是个数,记得+1)

          readfds:  读事件集合; // 键盘鼠标的输入,客户端连接都是读事件

          writefds: 写事件集合;  //NULL表示不关心

          exceptfds:异常事件集合;  //NULL 表示不关心

          timeout:   设为NULL,等待直到某个文件描述符发生变化;

                              设为大于0的值,有描述符变化或超时时间到才返回。

        超时时间检测:如果规定时间内未完成函数功能,返回一个超时的信息,我们可以根据该信息设定相应需求;

返回值:  <0 出错            >0 表示有事件产生;

                如果设置了超时检测时间:&tv

                <0 出错            >0 表示有事件产生;      ==0 表示超时时间已到;        

结构体如下:                     

            struct timeval {

               long    tv_sec;         以秒为单位,指定等待时间

               long    tv_usec;        以毫秒为单位,指定等待时间

           };

void FD_CLR(int fd, fd_set *set);  //将set集合中的fd清除掉 

int  FD_ISSET(int fd, fd_set *set); //判断fd是否在set集合中产生了事件

void FD_SET(int fd, fd_set *set);  //将fd加入到集合中

void FD_ZERO(fd_set *set);          //清空集合

(3)Select特点:

Select特点:

1. 一个进程最多只能监听1024个文件描述符 (32位)   [64位为 2048]

2. select被唤醒之后要重新轮询(0-1023)一遍驱动,效率低(消耗CPU资源)

3. select每次会清空未响应的文件描述符,每次都需要拷贝用户空间的表到内核空间,效率低,开销较大

   (0~3G是用户态,3G~4G是内核态,两个状态来回切换  拷贝是非常耗时,耗资源的)

 (4)select机制: 

1. 头文件检测1024个文件描述符  0-1023

2. 在select中0~2存储标准输入、标准输出、标准出错    

3. 监测的最大文件描述个数为fd+1(如果fd = 3,则最大为 4) :  //因为从0开始的    

4. select只对置1的文件描述符感兴趣 ,假如事件产生,select检测时 , 产生的文件描述符会保持1,未产生事件的会置0; 

5. select每次轮询都会清空表(置零的清空)   //需要在select前备份临时表

练习1:

如何通过select实现 响应鼠标事件同时响应键盘事件?

代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>int main(int argc, char const *argv[])
{int fd = open("/dev/input/mouse0", O_RDONLY);if (fd < 0){perror("open is err:");return -1;}//1.创建表fd_set readfds;//2/清空表FD_ZERO(&readfds);//3.设置表FD_SET(0, &readfds);FD_SET(fd, &readfds);fd_set readfdcp = readfds;int maxfd = fd;char buf[128] = {0};while (1){//4.检测是否有相应select(maxfd + 1, &readfds, NULL, NULL, NULL);//5.检测哪一个文件描述符if (FD_ISSET(0, &readfds)){fgets(buf, sizeof(buf), stdin);if (buf[strlen(buf) - 1] == '\n')buf[strlen(buf) - 1] = '\0';printf("key: %s\n", buf);}if (FD_ISSET(fd, &readfds)){int ret = read(fd, buf, sizeof(buf));buf[ret] = '\0';printf("mouse: %s\n", buf);}readfds = readfdcp;}return 0;
}

 练习2:

select是文件描述符和下标一一对应,0只能对应0号文件描述符。因此只有最大的文件描述符关闭时,才--len。注意增加删除时是针对实际表,不是临时表。

使用select实现server的全双工

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include <sys/select.h>int acceptfp;
int main(int argc, char const *argv[])
{char buf[128] = {0};//1.创建套接字,返回建立链接的文件描述符int sockfp = socket(AF_INET, SOCK_STREAM, 0);if (sockfp == -1){perror("socket is err");exit(0);}printf("%d\n", sockfp);//2.绑定ip和端口号struct sockaddr_in saddr, caddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(atoi(argv[1]));saddr.sin_addr.s_addr = inet_addr("0.0.0.0");socklen_t len = sizeof(struct sockaddr_in);if (bind(sockfp, (struct sockaddr *)&saddr, sizeof(saddr)) < 0){perror("bind is err");exit(0);}//3.listen监听if (listen(sockfp, 5)){perror("liste err");exit(0);}printf("listen ok\n");//1.创建表fd_set readfds;//2/清空表FD_ZERO(&readfds);//3.设置表FD_SET(0, &readfds);FD_SET(sockfp, &readfds);fd_set readfdcp = readfds;int maxfd = sockfp;struct timeval st;while (1){readfds = readfdcp;//4.检测是否有响应st.tv_sec = 5;st.tv_usec = 0;int ret = select(maxfd + 1, &readfds, NULL, NULL, &st);if (ret < 0){perror("select err");return -1;}else if (ret == 0){printf("无响应\n");}//0响应,证明服务器要发送消息if (FD_ISSET(0, &readfds)){fgets(buf, sizeof(buf), stdin);if (buf[strlen(buf) - 1] == '\n')buf[strlen(buf) - 1] = '\0';for (int i = 4; i <= maxfd; ++i){send(i, buf, sizeof(buf), 0);}}//sockfp,监听套接字响应证明,有客户端要链接if (FD_ISSET(sockfp, &readfds)){acceptfp = accept(sockfp, (struct sockaddr *)&caddr, &len);if (acceptfp < 0){perror("acceptfp");exit(0);}printf("port:%d   ip:  %s\n", ntohs(caddr.sin_port), inet_ntoa(caddr.sin_addr));FD_SET(acceptfp, &readfdcp);if (acceptfp > maxfd)maxfd = acceptfp;}//检测客户端,检查是哪一个客户端发送的消息for (int i = 4; i <= maxfd; ++i){if (FD_ISSET(i, &readfds)){int recvbyte = recv(i, buf, sizeof(buf), 0);if (recvbyte < 0){perror("recv err");return -1;}else if (recvbyte == 0){printf("%d client is exit\n", i);close(i);FD_CLR(i, &readfdcp);if (i == maxfd)--maxfd;}else{printf("%d : %s\n", i, buf);}}}}return 0;
}

练习3:

使用select实现client的全双工

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>int main(int argc, const char *argv[])
{int sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd < 0){perror("socker is err:");return -1;}struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(atoi(argv[1]));saddr.sin_addr.s_addr = inet_addr(argv[2]);if(connect(sockfd,(struct sockaddr *)&saddr,sizeof(saddr)) < 0){perror("connect is err:");return -1;}//1.创建表fd_set readfds,tempfds;//2.清空表FD_ZERO(&readfds);FD_ZERO(&tempfds);//3.添加文件描述符FD_SET(0,&readfds);FD_SET(sockfd,&readfds);int maxfd = sockfd;int ret;char buf[128];while(1){tempfds = readfds;//4.调select检测ret = select(maxfd+1,&tempfds,NULL,NULL,NULL);if(ret < 0){perror("select is err:");return -1;}if(FD_ISSET(0,&tempfds)){fgets(buf,sizeof(buf),stdin);if(buf[strlen(buf)-1] == '\n')buf[strlen(buf)-1] = '\0';send(sockfd,buf,sizeof(buf),0);}if(FD_ISSET(sockfd,&tempfds)){int recvbyte = recv(sockfd,buf,sizeof(buf),0);if(recvbyte < 0){perror("recv is err:");return -1;}printf("%s\n",buf);}}close(sockfd);return 0;
}

(5)select的超时时间检测:

超时检测的必要性:

1. 避免进程在没有数据时无限制的阻塞;

2. 规定时间未完成语句应有的功能,则会执行相关功能;

结构体如下:                     

            struct timeval {

               long    tv_sec;         以秒为单位,指定等待时间

               long    tv_usec;        以毫秒为单位,指定等待时间

           };

二.poll实现

 (1)poll流程

使用:  1.先创建结构体数组                                           struct pollfd fds[100];

          2.添加结构体成员的文件描述符以及触发方式   fds[0].fd = ?;fds[0].events = POLLIN 

          3.保存数组内最后一个有效元素的下标       

          4. 调用函数poll                                                  ret = poll(fds,nfds+1,-1);

          5.判断结构体内文件描述符是否触发事件          fds[i].revents == POLLIN

          6.根据不同的文件描述符触发不同事件 

(2)poll函数

声明:int poll(struct pollfd *fds, nfds_t nfds, int timeout);

头文件: #include<poll.h>

功能: 监视并等待多个文件描述符的属性变化

参数:

  1.struct pollfd *fds:   关心的文件描述符数组,大小自己定义

   若想检测的文件描述符较多,则建 立结构体数组struct pollfd fds[N]; 

           struct pollfd

           {

                  int fd;        //文件描述符

             short events;  //等待的事件触发条件----POLLIN读时间触发(大多数)

             short revents; //实际发生的事件(未产生事件: 0 ))

            }

    2.   nfds:        最大文件描述符个数

    3.  timeout: 超时检测 (毫秒级):1000 == 1s      

                          如果-1,阻塞          如果0,不阻塞

返回值:  <0 出错              >0 表示有事件产生;

              如果设置了超时检测时间:&tv

                <0 出错                >0 表示有事件产生;            ==0 表示超时时间已到;

(3)poll特点

1. 优化文件描述符个数的限制;

(根据poll函数第一个函数的参数来定,如果监听的事件为1个,则结构体数组容量为1,如果想监听100个,那么这个结构体数组的容量就为100,多少文件描述符由程序员自己来决定)

2. poll被唤醒之后需要重新轮询一遍驱动,效率比较低(消耗CPU)

3. poll不需重新构造文件描述符表(也不需清空表),只需要从用户空间向内核空间拷贝一次数据(效率相对比较高)

练习: 

使用poll实现server的全双工

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include <sys/select.h>
#include <poll.h>int acceptfp;
int main(int argc, char const *argv[])
{char buf[128] = {0};//1.创建套接字,返回建立链接的文件描述符int sockfp = socket(AF_INET, SOCK_STREAM, 0);if (sockfp == -1){perror("socket is err");exit(0);}printf("%d\n", sockfp);//2.绑定ip和端口号struct sockaddr_in saddr, caddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(atoi(argv[1]));saddr.sin_addr.s_addr = inet_addr("0.0.0.0");socklen_t len = sizeof(struct sockaddr_in);if (bind(sockfp, (struct sockaddr *)&saddr, sizeof(saddr)) < 0){perror("bind is err");exit(0);}//3.listen监听if (listen(sockfp, 5)){perror("liste err");exit(0);}printf("listen ok\n");//1.创建结构体数组struct pollfd fds[100];//2.添加文件描述符和触发方式fds[0].fd = 0;fds[0].events = POLLIN;fds[1].fd = sockfp;fds[1].events = POLLIN;int nfds = 1;int ret;while (1){//3.poll轮循检测ret = poll(fds, nfds + 1, 2000);if (ret < 0){perror("poll is err");return -1;}else if (ret == 0){printf("qeqweqe\n");continue;}//4. 判断哪一个文件描述符产生响应,并发布任务for (int i = 0; i <= nfds; ++i){if (fds[i].revents == POLLIN){if (fds[i].fd == 0){fgets(buf, sizeof(buf), stdin);if (buf[strlen(buf) - 1] == '\n')buf[strlen(buf) - 1] = '\0';//printf("发送信息:\n");for (int j = 2; j <= nfds; ++j){send(fds[j].fd, buf, sizeof(buf), 0);}}else if (fds[i].fd == sockfp){acceptfp = accept(sockfp, (struct sockaddr *)&caddr, &len);if (acceptfp < 0){perror("acceptfp");exit(0);}printf("port:%d   ip:  %s\n", ntohs(caddr.sin_port), inet_ntoa(caddr.sin_addr));fds[++nfds].fd = acceptfp;fds[nfds].events = POLLIN;}else{int recvbyte = recv(fds[i].fd, buf, sizeof(buf), 0);if (recvbyte < 0){perror("recv err");return -1;}else if (recvbyte == 0){printf("%d client is exit\n", i);close(fds[i].fd);//覆盖fds[i] = fds[nfds];//--i,--nfds后,最后一个循环不到--nfds, --i;}else{printf("%d : %s\n", i, buf);}}}}}return 0;
}

(4)poll超时时间检测

 timeout: 超时检测 (毫秒级):1000 == 1s      

                  如果-1,阻塞          如果0,不阻塞

三.epoll实现

(1)epoll流程:

Epoll的使用:

1.创建红黑树 和 就绪链表                                      int epfd = epoll_create(1);

2.添加文件描述符和事件信息到树上

    event.events = EPOLLIN|EPOLLET;

    event.data.fd = 0;

    epoll_ctl(epfd,EPOLL_CTL_ADD,0,&event

3.阻塞等待事件的产生,一旦产生事件,则进行处理 

     int ret = epoll_wait(epfd,events,32,-1);

4.根据链中准备处理的文件描述符 进行处理

(2)epoll函数族 

epoll 要使用一组函数:       epoll_create 创建红黑树 和 就序链表

                                          epoll_ctl   添加文件描述符和事件到树上 / 从树上删除

                                          epoll_wait  等待事件产生

epoll_create 

创建红黑树以及链表

头文件:#include <sys/epoll.h>

声明:int epoll_create(int size);

功能:创建红黑树根节点(创建epoll实例) , 同时也会创建就绪链表

返回值:成功时返回一个实例(二叉树句柄),失败时返回-1。

epoll_ctl

控制epoll属性

声明: int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

功能:控制epoll属性,比如给红黑树添加节点

参数:  1. epfd:   epoll_create函数的返回句柄。//一个标识符

          2. op:表示动作类型,有三个宏:         

                EPOLL_CTL_ADD:注册新的fd到epfd中

                EPOLL_CTL_MOD:修改已注册fd的监听事件

                EPOLL_CTL_DEL:从epfd中删除一个fd

3. 要操作的文件描述符

4. 结构体信息:

        typedef union epoll_data {

                int fd; //要添加的文件描述符,只用这个

                uint32_t u32; typedef unsigned int

                uint64_t u64; typedef unsigned long int

        } epoll_data_t;

        struct epoll_event {

                uint32_t events; 事件

                epoll_data_t data; //共用体(看上面)

        };

           关于events事件:

            EPOLLIN:  表示对应文件描述符可读

            EPOLLOUT: 可写

            EPOLLPRI:有紧急数据可读;

            EPOLLERR:错误;

            EPOLLHUP:被挂断;

            EPOLLET:触发方式,边缘触发;(默认使用边缘触发)

            ET模式:表示状态的变化;

            NULL: 删除一个文件描述符使用,无事件

返回值:成功:0, 失败:-1

epoll_wait

等待事件产生

声明: int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

功能:等待事件产生

   内核会查找红黑树中有事件响应的文件描述符, 并将这些文件描述符放入就绪链表

    就绪链表中的内容, 执行epoll_wait会同时复制到第二个参数events

参数:   epfd:句柄;

           events:用来保存从就绪链表中响应事件的集合;(传出参数,定义结构体数组)

           maxevents:  表示每次在链表中拿取响应事件的个数;

           timeout:超时时间,毫秒,0立即返回  ,-1阻塞

返回值: 成功: 实际从链表中拿出的数目     失败时返回-1

(4)epoll特点

1.监听的最大的文件描述符没有个数限制(取决与你自己的系统 1GB - 10万个左右)

2.异步I/O,epoll当有事件产生被唤醒之后,文件描述符主动调用callback(回调函数)函数直接拿到唤醒的文件描述符,不需要轮询,效率高

3.epoll不需要重新构造文件描述符表,只需要从用户空间向内核空间拷贝一次数据即可.

(5)epoll机制

select,poll都属于 同步IO机制(轮询)

epoll属于异步IO机制(不轮询): 

Epoll处理高并发,百万级

  1. 红黑树: 是特殊的二叉树(每个节点带有属性),Epoll怎样能监听很多个呢?首先创建树的根节点,每个节点都是一个fd以结构体的形式存储(节点里面包含了一些属性,callback函数)
  2. 就绪链表: 当某一个文件描述符产生事件后,会自动调用callback函数,通过回调callback函数来找到链表对应的事件(读时间还是写事件)。

 

 练习:

epoll实现server

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include <sys/select.h>
#include <poll.h>
#include <sys/epoll.h>int acceptfp;
int main(int argc, char const *argv[])
{char buf[128] = {0};//1.创建套接字,返回建立链接的文件描述符int sockfp = socket(AF_INET, SOCK_STREAM, 0);if (sockfp == -1){perror("socket is err");exit(0);}printf("%d\n", sockfp);//2.绑定ip和端口号struct sockaddr_in saddr, caddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(atoi(argv[1]));saddr.sin_addr.s_addr = inet_addr("0.0.0.0");socklen_t len = sizeof(struct sockaddr_in);if (bind(sockfp, (struct sockaddr *)&saddr, sizeof(saddr)) < 0){perror("bind is err");exit(0);}//3.listen监听if (listen(sockfp, 5)){perror("liste err");exit(0);}printf("listen ok\n");//1.创建红黑树以及链表//树的跟节点/树的句柄int epfd = epoll_create(1);//2.上树struct epoll_event event;struct epoll_event events[32] ;event.events = EPOLLET | EPOLLIN;event.data.fd = 0;epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &event);event.data.fd = sockfp;epoll_ctl(epfd, EPOLL_CTL_ADD, sockfp, &event);while (1){//3.阻塞等待文件描述符产生事件int ret = epoll_wait(epfd, events, 32, -1);printf("asdsdfgdsf\n");if (ret < 0){perror("epoll err");return -1;}//4.根据文件描述符号,进行处理for (int i = 0; i < ret; ++i){if (events[i].data.fd == 0){fgets(buf, sizeof(buf), stdin);if (buf[strlen(buf) - 1] == '\n')buf[strlen(buf) - 1] = '\0';printf("发送信息:\n");//send(fds[j].fd, buf, sizeof(buf), 0);}else if (events[i].data.fd == sockfp){acceptfp = accept(sockfp, (struct sockaddr *)&caddr, &len);if (acceptfp < 0){perror("acceptfp");exit(0);}printf("port:%d   ip:  %s\n", ntohs(caddr.sin_port), inet_ntoa(caddr.sin_addr));//上树event.data.fd = acceptfp;epoll_ctl(epfd, EPOLL_CTL_ADD, acceptfp, &event);}else{int recvbyte = recv(events[i].data.fd, buf, sizeof(buf), 0);if (recvbyte < 0){perror("recv err");return -1;}else if (recvbyte == 0){printf("%d client is exit\n", events[i].data.fd);close(events[i].data.fd);//下树epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);}else{printf("%d : %s\n", events[i].data.fd, buf);}}}}return 0;
}

对比 

http://www.ritt.cn/news/17683.html

相关文章:

  • 网络强国建设的未来西安seo网站推广优化
  • 做代购网站有哪些五年级上册语文优化设计答案
  • 淘客怎样做网站百度平台官网
  • 一级造价工程师报名seo优化工具哪个好
  • 怎样让公司网站更吸引人石景山区百科seo
  • wordpress 头部导航seo优化排名教程
  • 网站建设拟解决问题灰色行业怎么推广引流
  • 网站建设与开发大作业厦门人才网手机版
  • 网站做第三方登录seo培训教程视频
  • wordpress提权百度seo新算法
  • vs做网站的书籍线下推广团队
  • 彩票网站做一级代理犯法吗手机黄页怎么找
  • 做外贸必须关注的20个b2b网站_排名无先后苏州seo网络推广
  • 做网站看什么书好西安seo优化
  • 全国最新疫情一图读懂网站seo收录
  • 邢台网站改版制作公司百度联盟注册
  • 怎么做网站轮播图片产品网络营销策划方案
  • 怎么在手机上建网站百度热搜seo
  • 网站空间不够用百度手机助手下载2021新版
  • 怎么做网站推广世界杯推广产品的方法
  • 有没有做任务一样的网站兼职济南市最新消息
  • 2017做电商做什么网站seo每日一贴
  • 河南省鹤壁市住房和城乡建设局网站博为峰软件测试培训学费
  • 宽带办理多少钱一年网络推广优化服务
  • 网站建设及空间开封网站推广公司
  • 灵璧做网站的公司聊城seo优化
  • 阿里云需要网站建设方案书百度账号客服
  • 做3d效果的网站百度电话号码
  • 河北网站开发网站搜索引擎优化seo课程总结
  • 怎样做一个微信小程序网站优化课程培训