c++ socket实现的用kqueue实现多请求响应

本文介绍了在macOS环境下,由于epoll不适用于FreeBSD系统,因此选择了kqueue来实现Socket的多请求响应。kqueue的三个关键元素是struct kevent、EV_SET宏和kevent函数。通过kevent函数注册事件,处理读写操作。在实践中发现响应报文缺失分号导致浏览器解析问题,以及未初始化接收缓冲区导致段错误。更新中引入线程池解决了阻塞问题。
摘要由CSDN通过智能技术生成

这个版本更新主要是为了能使服务器能够同时处理多个请求。

最初有这个想法是因为这个博客最下面有一个select()函数,用来处理多个请求。之后又发现了epoll。发现了epoll之后本想写个小程序测试一下,但是却报了无法找到头文件的错误。这才意识到epoll是linux内核实现的,而我是用macOS开发的,macOS基于FreeBSD,也就是另一种类Unix系统。虽然都是类Unix系统,但是还是有些地方不一样,因此在这个环境下就用了kqueue,和epoll本质上是一样的,而且貌似用法要比epoll要简单。

这里有一篇比较系统的介绍epoll和kqueue之间的区别的文章。

据说kqueue只有三样东西:struct kevent结构体,EV_SET以及kevent函数。

struct kevent

结构体如下:

struct kevent {
   
    uintptr_t       ident;          /* identifier for this event,标识符,比如该事件关联的文件描述符 */
    int16_t         filter;         /* filter for event,过滤器,可以指定监听类型,如EVFILT_READ,EVFILT_WRITE,EVFILT_TIMER等 */
    uint16_t        flags;          /* general flags ,可以指定事件操作类型,比如EV_ADD,EV_ENABLE, EV_DELETE等 */
    uint32_t        fflags;         /* filter-specific flags */
    intptr_t        data;           /* filter-specific data */
    void            *udata;         /* opaque user data identifier,可以携带的任意数据 */
};

这个就类似于epoll中的epoll_event。

EV_SET

是一个用来初始化kevent函数的宏,其形式为:

EV_SET(&kev, ident, filter, flags, fflags, data, udata);

除了第一个参数以外,其他都和kevent中的成员相对应。

kevent函数

这个函数就是用来注册事件的,感觉像epoll_ctl和epoll_wait的结合。
其参数形式为:

int kevent(int kq, 
    const struct kevent *changelist, // 监视列表
    int nchanges, // 监视列表长度
    struct kevent *eventlist, // kevent函数用于返回已经就绪的事件列表
    int nevents, // 返回的就绪事件的长度
    const struct timespec *timeout); // 超时限制

另外注意:kevent与epoll最大的不同在于READ/WRITE事件是分开注册并且分开返回的,而Epoll则是一个fd一次返回读和写事件,用标志位来判断。

具体代码:

#include<cstdio>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<sys/event.h>
#include<sys/time.h>
#include<fcntl.h>
#include"WebServer.h"
using namespace std;

bool is_get_http(char* request){
   		//判断是否为GET请求
	return !strncmp(request,"GET",3);
}
char* get_file_name(char* buff){
   	//从请求中得到文件名
	//printf("DEBUG:-----%s-----\n\n",buff);
	if(buff==NULL||strlen(buff)<4)
		return NULL;
	char* fp=buff+4;
	char* Space=strchr(fp,' ');
	*Space='\0';
	return fp;
}
int get_file_size(char* file_name){
   	//得到文件大小	
	if
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值