网络编程——Linux高性能服务器编程阅读日记

Linux高性能服务器编程阅读日记——epoll两种触发模式比较

eopll,LT水平触发和ET边缘触发的区别,写了个简单的服务器代码测试了一下

#include<sys/types.h>
#include<sys/epoll.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<stdio.h>
#include<errno.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>

#define MAX_EVENT_NUMBER 1024
#define BUFFER_SIZE 10

//将文件描述符设置成非阻塞的
int setnonblocking(int fd)
{
	int old_option = fcntl(fd, F_GETFL);
	int new_option = old_option | O_NONBLOCK;
	fcntl(fd,F_SETFL,new_option);
	return old_option;
}

void addfd(int epollfd,int fd,bool enable_et)
{
	epoll_event event;
	event.data.fd = fd;
	event.events = EPOLLIN;
	if(enable_et)
		event.events |= EPOLLET;
	epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);
	setnonblocking(fd);
}

void lt(epoll_event* events,int number,int epollfd,int listenfd)
{
	char buf[BUFFER_SIZE];
	for(int i=0;i<number;i++)
	{
		int sockfd = events[i].data.fd;
		if(sockfd ==listenfd)
		{
			struct sockaddr_in client_address;
			socklen_t client_addrlength = sizeof(client_address);
			int connfd = accept(listenfd,
					(struct sockaddr*)&client_address,
					&client_addrlength);
			addfd(epollfd,connfd,false);//对connfd禁用ET模式
		}
		else if(events[i].events&EPOLLIN)
		{
			//只要socket读缓存中还有未读出的数据,这段代码就被触发
			printf("event trigger once\n");
			memset(buf,'\0',BUFFER_SIZE);
			int ret = recv(sockfd,buf,BUFFER_SIZE-1,0);
			if(ret<=0)
			{
				close(sockfd);
				continue;
			}
			printf("get %d bytes of content:%s\n",ret,buf);

		}
		else
			printf("something else happened\n");
	}
}

void et(epoll_event* events,int number,int epollfd,int listenfd)
{
        char buf[BUFFER_SIZE];
        for(int i=0;i<number;i++)
        {
                int sockfd = events[i].data.fd;
                if(sockfd ==listenfd)
                {
                        struct sockaddr_in client_address;
                        socklen_t client_addrlength = sizeof(client_address);
                        int connfd = accept(listenfd,(struct sockaddr*)&client_address,&client_addrlength);
                        addfd(epollfd,connfd,false);//对connfd禁用ET模式
                }
                else if(events[i].events&EPOLLIN)
                {
                        //只要socket读缓存中还有未读出的数据,这段代码就被触发
                        printf("event trigger once\n");
			while(1)
			{
			        memset(buf,'\0',BUFFER_SIZE);
				int ret = recv(sockfd,buf,BUFFER_SIZE-1,0);
				if(ret<0)
			        {
					if((errno==EAGAIN)||(errno==EWOULDBLOCK))
					{
						printf("read later\n");
						break;
					}
					close(sockfd);
					break;
				}
				else if(ret==0)
				        close(sockfd);
				else
				        printf("get %d bytes of content:%s\n",ret,buf);

			}
                }
                else
                        printf("something else happened\n");
        }
}

int main(int argc,char* argv[])
{
	const char* ip =argv[1];
	int port = atoi(argv[2]);

	int ret = 0;
	struct sockaddr_in address;
	bzero(&address,sizeof(address));
	address.sin_family = AF_INET;
	inet_pton(AF_INET,ip,&address.sin_addr);
	address.sin_port = htons(port);

	int listenfd = socket(PF_INET,SOCK_STREAM,0);
	assert(listenfd >= 0);

	ret = bind(listenfd,(struct sockaddr*)&address,sizeof(address));
	assert(ret!=-1);

	ret = listen(listenfd,5);
	assert(ret!=-1);

	epoll_event events[MAX_EVENT_NUMBER];
	int epollfd = epoll_create(5);
	assert(epollfd!=-1);
	addfd(epollfd,listenfd,true);

	while(1)
	{
		int ret = epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1);
		if(ret<0)
		{
			printf("epoll fail");
			break;
		}
		et(events,ret,epollfd,listenfd);
	}

}

telnet模拟http请求发送给服务端可以发现,发送超过十个字符的请求的时候两种模式的处理方式不同,LT模式未读取完成则还可以继续触发epoll事件,ET模式必须每次有IO请求就循环读取结束为止,否则下次不会再触发epoll事件。
看起来是LT模式比较智能,但是实际上,ET模式效率比较高,因为读取IO请求只需要触发一次。

《餐馆点餐管理系统——基于Java和MySQL的课程设计解析》 在信息技术日益发达的今天,餐饮行业的数字化管理已经成为一种趋势。本次课程设计的主题是“餐馆点餐管理系统”,它结合了编程语言Java和数据库管理系统MySQL,旨在帮助初学者理解如何构建一个实际的、具有基本功能的餐饮管理软件。下面,我们将深入探讨这个系统的实现细节及其所涉及的关键知识点。 我们要关注的是数据库设计。在“res_db.sql”文件中,我们可以看到数据库的结构,可能包括菜品表、订单表、顾客信息表等。在MySQL中,我们需要创建这些表格并定义相应的字段,如菜品ID、名称、价格、库存等。此外,还要设置主键、外键来保证数据的一致性和完整性。例如,菜品ID作为主键,确保每个菜品的唯一性;订单表中的顾客ID和菜品ID则作为外键,与顾客信息表和菜品表关联,形成数据间的联系。 接下来,我们来看Java部分。在这个系统中,Java主要负责前端界面的展示和后端逻辑的处理。使用Java Swing或JavaFX库可以创建用户友好的图形用户界面(GUI),让顾客能够方便地浏览菜单、下单。同时,Java还负责与MySQL数据库进行交互,通过JDBC(Java Database Connectivity)API实现数据的增删查改操作。在程序中,我们需要编写SQL语句,比如INSERT用于添加新的菜品信息,SELECT用于查询所有菜品,UPDATE用于更新菜品的价格,DELETE用于删除不再提供的菜品。 在系统设计中,我们还需要考虑一些关键功能的实现。例如,“新增菜品和价格”的功能,需要用户输入菜品信息,然后通过Java程序将这些信息存储到数据库中。在显示所有菜品的功能上,程序需要从数据库获取所有菜品数据,然后在界面上动态生成列表或者表格展示。同时,为了提高用户体验,可能还需要实现搜索和排序功能,允许用户根据菜品名称或价格进行筛选。 另外,安全性也是系统设计的重要一环。在连接数据库时,要避免SQL注入攻击,可以通过预编译的PreparedStatement对象来执行SQL命令。对于用户输入的数据,需要进行验证和过滤,防止非法字符和异常值。 这个“餐馆点餐管理系统”项目涵盖了Java编程、数据库设计与管理、用户界面设计等多个方面,是一个很好的学习实践平台。通过这个项目,初学者不仅可以提升编程技能,还能对数据库管理和软件工程有更深入的理解。在实际开发过程中,还会遇到调试、测试、优化等挑战,这些都是成长为专业开发者不可或缺的经验积累
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值