c++实现一个高并发服务器(三)服务器

CentOS下C++编程2——一个跨平台游戏服务器 C++跨平台服务器实现,TCP,HTTP 阅读详情

简介:

前面我实现了一个完整的动态线程池,接下来我要使用该线程池来实现服务器。下面介绍一下本服务器的基本特点。

  • 本服务器利用linux提供的epoll io复用技术来实现高并发访问
  • 对于客户端提供指定目录下文件的下载功能
  • 利用线程池来处理客户端的请求

前文
c++实现一个高并发服务器(二)线程池
c++实现一个高并发服务器(一)任务队列

组件

  • 服务器类 Server
成员简介
Server()创建线程池
~Server()释放线程池
run()进行端口和工作目录的设定,调用epollrun()
initListenFd()创建socket,绑定地址端口,监听等一些列操作
epollRun(int lfd)创建epoll,将服务器fd加入监听,循环监听
ThreadPool *m_pool线程池指针
  • 文件信息类 FdInfo
    用来封装一个文件描述符
成员简介
int fd文件描述符
int epfdepoll描述符
pthread_t tid对应的线程号
  • 一些用到的static 函数
函数简介
static void* acceptClient(void * arg);当epoll中监听服务器fd可读就代表有新的客户端连接,客户端连接处理函数,将新的客户端fd加入监听
static void* recvHttpRequest(void* arg);参数强制转换为FdInfo,从此fd中读取http请求,读取完毕后调用解析函数,即下面的函数
static int parseRequestLine(const char*line,int cfd);利用正则表达式将http请求中的method,path,protocol获取,将path转换为相对路径,发送http响应头和对应文件
static int sendHeadMsg(int cfd,int status,const char* descr,const char* type,int length);发送响应头,包括版本,状态码,状态码描述,content-type和content-length
static int sendFile(const char* fileName,int cfd);将对应文件发送给对应客户端fd
static int sendDir(const char* dirName,int cfd);使用一个文件名链表,获取当前目录所有文件名,根据每个文件的文件属性编写响应报文(检查是不是子目录),最后发送响应报文
static const char* getFileType(const char *name);解析文件名称,根据后缀名返回对应的html语句
static int hexToDec(char c);16进制的字符转10进制数字
static void decodeMsg(char * to,char * from);将16进制的http请求报文转换为10进制

流程图

在这里插入图片描述

Server.h

#pragma once

#include<pthread.h>
#include"ThreadPool.h"
#include"TaskQueue.h"

struct FdInfo{
	int fd;
	int epfd;
	pthread_t tid;
};
class Server{
public:
	Server();
	~Server();

	int run(int argc, char* argv[]);
private:
	int initListenFd(unsigned short port);
	int epollRun(int fd);
private:
	ThreadPool *m_pool;
};

Server.cpp

#include"Server.h"
#include<arpa/inet.h>
#include<stdio.h>
#include<fcntl.h>
#include<errno.h>
#include<strings.h>
#include<string.h>
#include<sys/stat.h>
#include<assert.h>
#include<sys/epoll.h>
#include<sys/sendfile.h>
#include<dirent.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<ctype.h>

static void* acceptClient(void * arg);
static void* recvHttpRequest(void* arg);

static int parseRequestLine(const char*line,int cfd);
static int sendHeadMsg(int cfd,int status,const char* descr,const char* type,int length);
static int sendFile(const char* fileName,int cfd);
static int sendDir(const char* dirName,int cfd);
static const char* getFileType(const char *name);
static int hexToDec(char c);
static void decodeMsg(char * to,char * from);

Server::Server(){
	m_pool=new ThreadPool(8,8);
}

Server::~Server(){
	if(m_pool!=nullptr){
		delete m_pool;
		m_pool=nullptr;
	}
}

int Server::run(int argc,char* argv[]){
	if(argc<3){
		printf("Please input : ./xxx port path\n");
		return -1;
	}
	unsigned short port=atoi(argv[1]);
	chdir(argv[2]);

	printf("Init listen...\n");
	int lfd=initListenFd(port);
	if(lfd==-1){
		return -1;
	}

	printf("epoll run ...\n");
	epollRun(lfd);

	return 0;
}

int Server::initListenFd(unsigned short port){

	//1.create socket 
	int lfd=socket(AF_INET, SOCK_STREAM, 0);
	if(lfd==-1){
		perror("socket");
		return -1;
	}

	//2.set addr reuse
	int opt=1;
	int ret=setsockopt(lfd, SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
	if(ret==-1){
		perror("setsockopt");
		return -1;
	}

	//3.bind the addr
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr =INADDR_ANY;
	addr.sin_port = htons(port);
	ret=bind(lfd,(struct sockaddr *)&addr,sizeof(addr));
	if(ret==-1){
		perror("bind");
		return -1;
	}

	//4.set listen
	ret=listen(lfd,128);
	if(ret==-1){
		perror("listen");
		return -1;
	}

	return lfd;
}

int Server::epollRun(int lfd){
	//1.create a epoll instance
	int epfd=epoll_create(1);
	if(epfd==-1){
		perror("eppoll_create");
		return -1;
	}

	//2.register lfd in epoll
	struct epoll_event ev;
	ev.data.fd=lfd;
	ev.events=EPOLLIN;
	int ret=epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);
	if(ret==-1){
		perror("epoll_create");
		return -1;
	}

	//loop to check
	struct epoll_event evs[1024];
	int size=sizeof(evs)/sizeof(struct epoll_event);
	while(1){
		int num=epoll_wait(epfd,evs,size,-1);
		for(int i=0;i<num;++i){
			int fd=evs[i].data.fd;
			struct FdInfo* info=new struct FdInfo;
			info->fd=fd;
			info->epfd=epfd;
			if(fd==lfd){
				acceptClient(info);
				printf("acceptClient...\n");
				usleep(1);
			}else{
				printf("recvHttpRequest...\n");
				m_pool->addTask(Task(recvHttpRequest,info));
				usleep(1);
			}
		}
	}
	return 0;
}

static void * acceptClient(void* arg){
	printf("acceptClient threadId:%ld\n",pthread_self());
	struct FdInfo* info=(struct FdInfo*)arg;
	//1.establish connection
	int cfd=accept(info->fd,NULL,NULL);
	if(cfd==-1){
		perror("accept");
		return NULL;
	}

	//set cfd is noblock 
	int flag=fcntl(cfd,F_GETFL);
	flag |=O_NONBLOCK;
	fcntl(cfd,F_SETFL,flag);

	//add cfd to epoll
	struct epoll_event ev;
	ev.data.fd=cfd;
	ev.events=EPOLLIN|EPOLLET;
	int ret=epoll_ctl(info->epfd,EPOLL_CTL_ADD,cfd,&ev);
	if(ret==-1){
		perror("epoll_ctl");
		return NULL;
	}

	free(info);
	return NULL;
}


static void* recvHttpRequest(void *arg){
	printf("recvHttpRequest threadId:%ld\n",pthread_self());
	struct FdInfo* info=(struct FdInfo*)arg;

	int len=0,total=0;
	char tmp[1024]={0};
	char buf[4096]={0};
	while((len=recv(info->fd,tmp,sizeof tmp,0))>0){
		if(total+len<sizeof buf){
			memcpy(buf+total,tmp,len);
		}
		total=total+len;
	}

	if(len==-1&&errno==EAGAIN){
		parseRequestLine(buf,info->fd);
	}else if(len==0){
		epoll_ctl(info->epfd,EPOLL_CTL_DEL,info->fd,NULL);
		close(info->fd);
	}else{
		perror("recv");
	}
	free(info);
	return NULL;
}

static int parseRequestLine(const char *line ,int cfd){
	printf("pareRequestLine...\n");
	char method[12]="";
	char path[1024]="";
	char protocol[256]="";
	
	sscanf(line,"%[^ ] %[^ ] %[^ \r\n]",method,path,protocol);
	printf("before decode: [%s]  [%s]  [%s]\n",method,path,protocol);
	decodeMsg(path,path);
	printf("after decode: [%s]  [%s]  [%s]\n",method,path ,protocol);

	

	if(strcasecmp(method,"get")!=0){
		printf("not get\n");
		return -1;
	}

	char *file=NULL;
	
	//deal the static file which client asked
	if(strcmp(path,"/")==0){
		file="./";
	}else{
		file=path +1;
	}

	//get file property
	struct stat st;
	int ret=stat(file,&st);
	if(ret==-1){
		//file not exist
		sendHeadMsg(cfd,404,"Not Found",getFileType(".html"),-1);
		sendFile("404.html",cfd);
		return 0;
	}
	if(S_ISDIR(st.st_mode)){
		sendHeadMsg(cfd,200,"OK",getFileType(".html"),-1);
		sendDir(file,cfd);
	}else{
		sendHeadMsg(cfd,200,"OK",getFileType(file),st.st_size);
		sendFile(file,cfd);
	}

	return 0;

}

static int sendHeadMsg(int cfd,int status,const char* descr,const char* type,int length){
	//response line
	char buf[4096]={0};
	sprintf(buf,"HTTP/1.1 %d %s\r\n",status,descr);
	
	//response head
	sprintf(buf+strlen(buf),"content-type:%s\r\n",type);
	sprintf(buf+strlen(buf),"content-length:%d\r\n\r\n",length);

	send(cfd,buf,strlen(buf),0);
	return 0;
}

static int sendFile(const char* fileName,int cfd){
	printf("send file: %s\n",fileName);
	int fd=open(fileName,O_RDONLY);
	assert(fd>0);
	int size=lseek(fd,0,SEEK_END);
	lseek(fd,0,SEEK_SET);
	off_t offset=0;
	while(offset<size){
		//sendfile function has limitation of sending
		int ret=sendfile(cfd,fd,&offset,size-offset);
		usleep(1);
		printf("ret=%d\n",ret);
		if(ret==-1){
			if(errno==EAGAIN){
				printf("no data.../");
			}
			perror("sendfile");
		}

	}
	close(fd);
	return 0;
}

static int sendDir(const char* dirName,int cfd){
	printf("send Dir:%s\n",dirName);
	char buf[4096]={0};
	sprintf(buf,"<html><head><title>%s</title></head><body><table>",dirName);
	struct dirent** namelist;//point to a pointer array
							 //struct dirent* tmp[]
	int num=scandir(dirName,&namelist,NULL,alphasort);
	for(int i=0;i<num;i++){
		char *name=namelist[i]->d_name;
		struct stat st;
		char subPath[1024]={0};
		sprintf(subPath,"%s/%s",dirName,name);
		stat(subPath,&st);
		if(S_ISDIR(st.st_mode)){
			sprintf(buf+strlen(buf),
				"<tr><td><a href=\"%s/\">%s</a></td>%ld</td></tr>",
				name,name,st.st_size);
		}else{
			sprintf(buf+strlen(buf),
				"<tr><td><a href=\"%s\">%s</a></td><td>%ld</td></tr>",
				name,name,st.st_size);
		}
		send(cfd,buf,strlen(buf),0);
		memset(buf,0,sizeof(buf));

		free(namelist[i]);
	}
	sprintf(buf,"</table></body></html>");
	send(cfd,buf,strlen(buf),0);

	free(namelist);
	return 0;

} 

static const char* getFileType(const char* name){
	const char *dot=strrchr(name,'.');
//judge file type by file name
	if(dot==NULL)
		return "text/plain;charset=utf-8";
	if(strcmp(dot,".html")==0||strcmp(dot,"htm")==0)
		return "text/html;charset=utf-8";
	if(strcmp(dot,".jpg")==0||strcmp(dot,".jpeg")==0)
		return "image/jpeg";
	if(strcmp(dot,".gif")==0)
		return "image/gif";
	if(strcmp(dot,".png")==0)
		return "image/png";
	if(strcmp(dot,".css")==0)
		return "text/css";
	if(strcmp(dot,"au")==0)
		return "audio/.au";
	if(strcmp(dot,".wav")==0)
		return "audio/.wav";
	if(strcmp(dot,".avi")==0)
		return "video/x-msvideo";
	if(strcmp(dot,".mov")==0||strcmp(dot,".qt")==0)
		return "video/quicktime";
	if(strcmp(dot,".mpeg")==0||strcmp(dot,".mpe")==0)
		return "video/mepeg";
	if(strcmp(dot,".mp3")==0)
		return "audio/mpeg";
	if(strcmp(dot,".vrml")==0)
		return "model/vrml";
	if(strcmp(dot,".ogg")==0)
		return "application/ogg";
	if(strcmp(dot,".pac")==0)
		return "application/x-nx-proxy-autoconfig";

	return"text/plain;charset=utf-8";
}

static int hexToDec(char c){
	if(c>='0'&&c<='9')
		return c-'0';
	if(c>='a'&&c<='f')
		return c-'a'+10;
	if(c>='A'&&c<='F')
		return c-'a'+10;

	return 0;
}

static void decodeMsg(char* to,char* from){
	for(;*from!='\0';++to,++from){
		//judge from %20 3 chars 
		if(from[0]=='%'&&isxdigit(from[1])&&isxdigit(from[2])){
		//turn hex to dec
		//3 chars become 1 char ,this original data
			*to=hexToDec(from[1])*16+hexToDec(from[2]);
			from+=2;
		}else{
			*to=*from;
		}
	}
	*to='\0';
}

main.cpp

#include<stdio.h>
#include"Server.h"
#include<unistd.h>
#include<stdlib.h>

int main(int argc, char **argv){
	Server server;
	return server.run(argc,argv);
	return 0;
}

测试

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

总结

到这里我们的高并发服务器基本上以及实现完毕了,后续还会做一些小的改进,或者添加一些新的功能。

手搓 HTTP服务器 手把手带你实现C++高并发HTTP服务器 C++ 高性能服务器项目实战 手把手带你实现高并发HTTP服务器,内容包含正则表达式,字符串处理,socket 通讯,文件读写处理 阅读详情

相关推荐

C++高并发异步定时器的实现

getchar();return 0;本篇介绍了如何优雅地处理异步任务的:创建、发起、回调、取消、进程退出多种并发行为,其中包含了许多常用的技巧!不记得的小伙伴自行翻回去再看一遍._.当然这在并发的世界中还只是冰山一角,因为很有可能写下某一句话的时机不对,任务一结束,程序就GG了。

2401_86353562的博客 1155

C++第4课:C++协程及高并发网络协程库State-Threads

C++第4课:C/C++协程及高并发网络协程库State-Threads大家好,我将带领大家一起来学习CC/C++协程的基础知识,包括setjmp, longjmp,和ucontext。然后讲解汇编语言的CPU寻址,以及CS:IP控制CPU走向的原理。然后讲解高并发网络协程库State-Threads的案例应用,开发上万个协程,以及TCP服务器案例。本课程的内容主要包括C/C++语言的setjmp、longjmp和goto,C/C++语言的协程简介、8086汇编语言的CS和IP寄存器及寻址、异步I/O+epoll+协程、IO复用机制、Linux协程之ucontext组件、Linux协程之生产者消费者、高并发网络协程库State-Threads、用State-Threads创建高并发TCP服务器等。 

C++并发服务器的实现

本人自己实验课写的,需要在客户端的源代码中绑定套接字处填写自己的本地IP地址。使用说明:先开启并发服务器,再开启多个客户端。 很简单的一个小实验,供大家学习套接字以及多线程技术。

【Linux】C++项目实战-高并发服务器详析

介绍了高并发服务器的相关内容

mhyasadj的博客 2809

基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip

【资源说明】 基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip 基于Reactor高并发服务器 c++源码+详细项目说明+sln解决方案.zip 基于`Reactor`高并发服务器 `C++` > 基于`Reactor`的高并发服务器,分为`反应堆模型`,`多线程`,`I/O模型`,`服务器`,`Http请求`和`响应`五部分 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

用Python+ArcGIS分析厦门共享单车数据:5分钟搞定订单时长与距离分布的可视化

本文详细介绍了如何利用Python和ArcGIS Pro 3.x快速分析厦门共享单车数据,实现订单时长与距离分布的可视化。通过数据清洗、预处理和高级可视化技巧,揭示用户行为特征,为运营优化提供数据支持。文章还提供了环境配置、代码示例和业务洞察,帮助开发者高效完成数据分析任务。

weixin_28327051的博客 336

C/C++实现高并发http服务器

使用从C/C++语言构建高并发http服务器,使用多线程技术实现http服务器高并发,使用户不会感觉到服务器用户过多,导致体验感很差。

qq_45041871的博客 3528

差分式升压逆变器MATLAB仿真模型设计——实现110V/50Hz输出电压与THD<5%

差分式升压逆变器MATLAB仿真设计 摘要 本文提出一种基于差分式升压逆变器(DBI)的MATLAB仿真设计方案,实现80V直流输入转换为110V/50Hz交流输出。该方案采用单级升压逆变拓扑结构,相比传统两级方案具有更高的功率密度和效率。通过建立数学模型,设计SPWM调制策略和电压闭环PI控制,并在MATLAB/Simulink中构建完整仿真模型。仿真结果表明,系统输出电压THD<5%,满足设计要求。文章详细阐述了主电路参数计算、控制策略实现和仿真验证过程,为实际工程应用提供了理论依据和技术参考。

huanghm88的专栏 121

C/C++实现高并发http服务器的代码示例

C/C++实现高并发http服务器的代码示例

m0_60259116的博客 1943

从底层结构开始学习FPGA(8)----Block RAM(BRAM,块RAM)

BRAM作为FPGA底层的存储资源,作用很大,比如可以RAM/ROM/FIFO。

孤独的单刀 2万+

uniapp [全端兼容] - 实现人脸识别对比+人脸相似度,从相册选择或拍照上传两张图片进行人脸对比得到人脸相似度及判断是否是同一个人,人脸活体检测及对比(免费纯前端方案+调用第三方API接口方案)

uniApp人脸对比 人脸对比识别 人脸对比相似度,uniapp实现获取手机摄像头权限,调用相机拍照实现人脸识别相似度对比,uniapp实现人脸识别对比,计算两张人脸的相似度,从而判断是否同一个人,并给出相似度评分。uniapp H5网页如何实现人脸相似度比对,uniapp纯前端怎么对比两张图片的相似度,计算两幅图像的相似度,图像相似度对比方法,UNI-APP人脸相似度对比,快速识别两张照片的相似程度(用百分比)图片相似度对比在线测试,图片相似度对比,uniapp微信小程序人脸相似度对比分析,uniapp

🏆 前端领域优质创作者 5020

c++ 高并发服务器详解

本文列举两个c++并发服务器,并尝试分析其中语法,若有错误,还望指正。这里不讨论socket和c/s架构,只对服务器端做分析。 服务器处理任务的大体流程是: 服务器启动线程,开始等待和接收任务,处理任务,退出线程。接收任务时,任务被添加在全局的一个队列,被所有线程共享,这时就考虑一个同步。如果任务队列为空或者太满,还需要考虑线程池的容量大小。 这不禁让人想起了经典的生产者—消费着模式,生产者生产一个任务,消费者耗费一个任务,很类似,大概流程如下草图所示: 这里用到了互斥量锁,条件变量,..

aDiligentCigarette的博客 4015

模型泛化能力提升:领域自适应与迁移学习

模型泛化能力提升:领域自适应与迁移学习​ ,人工智能,计算机视觉,大模型,AI,在机器学习和深度学习的应用中,模型的泛化能力是一个关键问题。泛化能力指的是模型在新的、未见过的数据上表现良好的能力。然而,实际情况中,训练数据和测试数据往往来自不同的领域,存在分布差异,这会导致模型的泛化能力下降。领域自适应与迁移学习正是为了解决这一问题而发展起来的重要技术。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 3万+

【C++高并发服务器WebServer】-12:TCP详解及实现

欢迎来到Golinie的频道,这里是C++并发服务器专题。本篇文章主要围绕TCP通信展开,详细介绍了TCP通信流程以及关键的套接字函数,包括socket()、bind()、listen()、accept()和connect()。同时,通过server端和client端的代码示例,展示了并发服务器的实现过程。此外,还深入探讨了TCP三次握手、滑动窗口机制以及四次挥手过程,最后介绍了多进程并发服务器的设计思路。

theaipower的博客 1万+

基于STM32的室内环境监测系统设计与实现

摘要 本文设计了一种基于STM32的室内环境监测系统,通过传感器实时采集温湿度、空气质量、烟雾浓度等数据,并利用Wi-Fi模块上传至云服务器。系统采用STM32F103C8T6作为主控芯片,结合DHT11、MQ系列传感器及BMP280气压传感器实现数据采集,通过ESP8266模块实现远程数据传输。用户可通过手机APP实时查看环境参数,并在数据超标时触发报警。实验表明,系统运行稳定,监测精度高,具有低成本、易扩展等特点,为改善室内环境质量提供了有效解决方案。 关键词:STM32;室内环境监测;传感器;Wi-F

3254968421的博客 221

LeRobot 入门教程(七)数据集

LeRobot Dataset v3.0 是机器人学习数据的标准化格式,支持多模态时间序列数据和视频的统一访问。该版本通过基于文件的存储(Parquet/MP4)、关联元数据和Hub原生流式处理等新特性,显著提升了性能并降低了存储开销。文档详细介绍了格式设计、安装使用、数据记录与加载方法,以及从v2.1迁移到v3.0的步骤,特别针对大型数据集(如DROID 1.0.1)的处理提供了SLURM集群移植方案。v3.0通过优化文件组织和元数据管理,实现了更快的加载速度、更高的内存效率和更好的可扩展性。

2506_90492529的博客 2054

C++高并发网络架构与实现——完成进度

学会使用C++实现从1个用户连接到10000个用户链接,从每秒1个用户/1个数据包,到1万用户/1百万个数据包,最终实现高并发服务器

双鱼座boyy的博客 2345

04-协议基础03:USB 2.0信号与电气特性

USB 2.0使用两根差分信号线D+/D-进行数据传输,支持低速(1.5Mbps)、全速(12Mbps)和高速(480Mbps)三种速率。USB总线为主从模式,所有事务由Host发起。端电阻值作用HostRpd(D+)15KΩ±5%下拉,默认低电平HostRpd(D-)15KΩ±5%下拉,默认低电平全速设备Rpu(D+)1.5KΩ±5%上拉到3.3V,标识全速低速设备Rpu(D-)1.5KΩ±5%上拉到3.3V,标识低速USB 2.0硬件要点。

内核笔记 104

C++ 网络通信实践:cpp-httplib 与 websocketpp 入门指南,轻松实现 HTTP 与 WebSocket 交互

本文介绍 cpp - httplib 和 websocketpp 两个 C++ 库。前者轻量易用,支持 HTTP/HTTPS 客户端和服务端,适用于多种场景;后者遵循 RFC 6455,实现 WebSocket 全双工通信,帮助实现实时应用开发。

羑悻的博客. 3万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

仿照muduo库实现一个高并发服务器

本项目实现了一个基于C++的高性能Reactor模式网络库,采用主从Reactor模型实现高并发TCP服务器

adorable_C0C0nut的博客 903

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

使用libevent库实现惊人的高并发C++服务器!

libevent是一个事件通知库,封装了reactor。libevent API 提供了一种机制,用于在文件描述符上发生特定事件或达到超时后执行回调函数。此外,libevent还支持由于信号或常规超时而导致的回调。libevent 旨在替换在事件驱动的网络服务器中找到的事件循环。应用程序只需要调用event_dispatch(),然后动态添加或删除事件,而无需更改事件循环。

Lion_Long的博客 1937

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

【c++实战项目】从零实现一个高并发内存池

【c++实战项目】从零实现一个高并发内存池

m0_74722801的博客 1438

C/C++实现简单高并发http服务器

C/C++实现简单的高并发http服务器

hulinhulin的专栏 965

C++高并发服务器设计(三)

C++高并发服务器设计(三) 客户端升级发送结构化网络消息

君莫笑的博客 5180

【项目学习】C++实现高并发服务器——环境搭建

项目来源:WebServer 用C++实现的高性能WEB服务器,经过webbenchh压力测试可以实现上万的QPS 功能 利用IO复用技术Epoll与线程池实现多线程的Reactor高并发模型; 利用正则与状态机解析HTTP请求报文,实现处理静态资源的请求; 利用标准库容器封装char,实现自动增长的缓冲区; 基于小根堆实现的定时器,关闭超时的非活动连接; 利用单例模式与阻塞队列实现异步的日志系统,记录服务器运行状态; 利用RAII机制实现了数据库连接池,减少数据库连接建立与关闭的开销,同时实现了用户注册

vhcjgc的博客 3926
上一篇: libevent库学习 event_base和event
下一篇: libevent学习 evhttp
Sweler*19
博客等级 码龄7年 65粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值