epoll实例(Linux)

epoll实例详解
本文提供了一个epoll实例的详细解析,包括如何使用epoll进行网络编程,如何处理客户端连接及数据收发等核心操作。通过这个例子,读者可以了解epoll的工作原理及其在实际应用中的运用。

epoll 实例练习

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 

#include  
#include  
#include  
#include  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

const unsigned char PACKET_FLAGS_ZLIB = 0x1;
const unsigned int BUFSIZE = 1024 * 96;
const unsigned int PH_LEN = sizeof (unsigned int) + sizeof (unsigned char);
const unsigned int PACKET_ZIP_MIN =32;
const unsigned char PACKET_FLAGS_ZIP = 0x02;
const unsigned int MAX_DATASIZE = BUFSIZE - 1 - PH_LEN;
const unsigned int LISTEN_MAX = 2000;
const unsigned int EVENTS_MAX = 256;
bool bfinal = false;

#define gettid() syscall(SYS_gettid)
#define geterror() printf("%s:%d tid:%d error:%s\n", __FUNCTION__, __LINE__, gettid(), strerror(errno))
/*
#define TEMP_FAILURE_RETRY(expression) \  
  (__extension__\  
   ({ long int __result;\  
       do __result = (long int)(expression);\  
       while(__result == -1L&& errno == EINTR);\  
       __result;})\  
#endif  
*/

void setnonblocking(int sock) 
{     
    int opts;     
    opts = fcntl(sock,F_GETFL);     
    if (opts < 0)     
    {         
        perror("fcntl(sock,GETFL)");         
        exit(1);     
    }     
    opts = opts|O_NONBLOCK;     
    if (fcntl(sock, F_SETFL, opts) < 0)     
    {         
        perror("fcntl(sock,SETFL,opts)");         
        exit(1);     
    }  
}

void ctrlcHandler(int signum)
{
	bfinal = true;
}
void hupHandler(int signum)
{

}

void setSigaction()
{
	struct sigaction sig;

    sig.sa_handler = ctrlcHandler;
    //sigemptyset(&sig.sa_mask);
	sigaction(SIGUSR1, &sig, NULL);
    sig.sa_flags = 0;
    sigaction(SIGINT, &sig, NULL);
    sigaction(SIGQUIT, &sig, NULL);
    sigaction(SIGABRT, &sig, NULL);
    sigaction(SIGTERM, &sig, NULL);
    sig.sa_handler = hupHandler;
    sigaction(SIGHUP, &sig, NULL);
    sig.sa_handler = SIG_IGN;
    ///在写到管道时读进程终止,则产生该信号,
    ///当类型为SOCK_STREAM的套接字不再连接时,进程写到该套接字产生该信号,忽略该信号,否则一旦客户端失去连接,程序就退出。
    sigaction(SIGPIPE, &sig, NULL);
}

int main(int argc, char* argv[])
{
	//后台运行
	//daemon(1, 0);
	//设置信号处理
	setSigaction();
	std::map mapSock;
	unsigned char sendBuf[BUFSIZE];
	unsigned char recvBuf[BUFSIZE];
	unsigned int recvLen;
	int sockfd;		//监听fd
	struct sockaddr_in servaddr;
	char bind_host[20];
    memset(bind_host, 0, sizeof(bind_host));
	memset(&servaddr, 0, sizeof(servaddr));
	sprintf(bind_host, "%s", "127.0.0.1");
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(22222);
	/*
	if( -1 == inet_addr("255.255.255.255") )
		cout<<"error"< 0 )
				{
					setnonblocking(sockcoon);
					//ev.events = EPOLLIN | EPOLLOUT | EPOLLET;
					ev.events = EPOLLIN | EPOLLERR | EPOLLPRI | EPOLLET;
					ev.data.fd = sockcoon;
                    int error_num = 0;
					if (-1 == ( error_num = epoll_ctl(epfd, EPOLL_CTL_ADD, sockcoon, &ev) ) )
					{
                        printf("test: add %d | error:%d\n", sockcoon, error_num);
						close(sockcoon);
						perror("epoll_ctl: add error"); //连接套接字
					}
					mapSock[sockcoon] = sockcoon;
					printf("connect success sock:%d\n", sockcoon);
				}
			}
			else if( events[i].events & (EPOLLERR|EPOLLPRI) )
			{
				if (events[i].events & EPOLLERR)
				{
					int error = 0;
                    socklen_t errlen = sizeof( error );
					if ( getsockopt( events[i].data.fd, SOL_SOCKET, SO_ERROR, ( void* )&error, &errlen) )
						printf("%s:%d, pid:%d,tid=%d: epoll error: %d\n", __PRETTY_FUNCTION__, __LINE__, getpid(), gettid(),  error);
					printf("%s:%d, pid:%d,tid=%d: connection error\n", __PRETTY_FUNCTION__, __LINE__, getpid(), gettid());
					mapSock.erase(events[i].data.fd);
					if (-1 == epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, &ev) )
					{
        				printf("%s:%s\n", __FUNCTION__,strerror(errno));
					}
					shutdown(events[i].data.fd, SHUT_RDWR);
					close(events[i].data.fd);
					events[i].data.fd = -1;
				}
				else
				{
					printf("%s:%d, pid:%d,tid=%d: connection error:get out-of-band data\n", __PRETTY_FUNCTION__, __LINE__, getpid(), gettid());
					mapSock.erase(events[i].data.fd);
					if (-1 == epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, &ev) )
                    {
                        printf("%s:%d %s\n", __FUNCTION__, __LINE__, strerror(errno));
                    }
					shutdown(events[i].data.fd, SHUT_RDWR);
					close(events[i].data.fd);
					events[i].data.fd = -1;
				}
			}
			else if( events[i].events & EPOLLIN )	//如果是已经连接的用户,并且收到数据,那么进行读入。
			{
				int n = 0;
				int read = 0;
				/// linux下当连接断开,还发数据的时候,会向系统发送一个异常消息,如果不作处理,系统会出BrokePipe,程序会退出。
    			/// 为此,函数的最后一个参数设置MSG_NOSIGNAL,禁止向系统发送异常消息。
				n = TEMP_FAILURE_RETRY(::recv(usesock, recvBuf+read, BUFSIZE, MSG_NOSIGNAL));
				/// 非阻塞下 收到EAGAIN 或EWOULDBLOCK,表明套接口没有数据读写,或者收到其他新号的中断
				if( -1 == n && (errno == EAGAIN || errno == EWOULDBLOCK) )
				{

				}
				else if( 0 == n )
				{
					//对端关闭
					mapSock.erase(events[i].data.fd);
					if (-1 == epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, &ev))
                    {
                        printf("%s:%d %s\n", __FUNCTION__, __LINE__, strerror(errno));
                    }
					shutdown(events[i].data.fd, SHUT_RDWR);
					close(usesock);
					events[i].data.fd = -1;
					printf("%s:%d, tid=%d: recv EOF: n = 0\n", __PRETTY_FUNCTION__, __LINE__, gettid() );
					geterror();
				}
				else
				{
					//success recv
					//每个sock都应该有接收队列,這里只是测试
					printf("success recv len:%d:%s\n", n, recvBuf);
					memset(recvBuf, 0, sizeof(recvBuf));
				}
			}
			else if( events[i].events & EPOLLOUT )	//如果是已经连接的用户,并且有数据发送,那么进行写入。
			{
				int n = 0;
				int sendLen = 0;
				if( sendLen = strlen((char *)sendBuf) < BUFSIZE )
					sendBuf[sendLen+1] = sendLen%10;
				n = TEMP_FAILURE_RETRY(::send(usesock, sendBuf, sendLen+2, MSG_NOSIGNAL));
				if( -1 == n && (errno == EAGAIN || errno == EWOULDBLOCK) )
                {

                }
				else if( n > 0 )
				{
					printf("send success len:%d:%s\n", n, sendBuf);
					if( n > 200 )
						memset(sendBuf, 0, sizeof(sendBuf));
				}
			}
		}
	}

	for(std::map::iterator itr = mapSock.begin(); itr != mapSock.end(); ++itr)
	{
		if( itr->second )
		{
			printf("close fd :%d \n", itr->second);
			if (-1 == epoll_ctl(epfd, EPOLL_CTL_DEL, itr->second, &ev))
			{
				//printf("%s:%d %s\n", __FUNCTION__, __LINE__, strerror(errno));
				geterror();
			}
			shutdown(itr->second, SHUT_RDWR);
			close(itr->second);
		}
	}
	close(sockfd);
	close(epfd);
	return 0;
}
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
    int sockfd = 0;
    sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if( sockfd <= 0 )
        return -1;

    socklen_t len = 0;
    struct sockaddr_in servaddr;
    char bind_host[20];
    memset(bind_host, 0, sizeof(bind_host));
    memset(&servaddr, 0, sizeof(servaddr));
    sprintf(bind_host, "%s", "127.0.0.1");
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(22222);
    if( inet_pton(AF_INET, bind_host, &servaddr.sin_addr) <= 0 ){
        printf("inet_pton error for %s\n", bind_host);
        exit(0);
    }

    if( connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 )
    {
        printf("connect error\n");
        close(sockfd);
        return -2;
    }

    int n = 0;
    for(int i= 100; i< 200; i+=20)
    {
        char buff[100];
        sprintf(buff, "%d", i);
        while( (n = send(sockfd, buff, sizeof(buff), MSG_NOSIGNAL)) < 0 )
        {
            
        }
        printf("send len :%d\n", n);
    }

    sleep(10);
	shutdown(sockfd, SHUT_RDWR);
    close(sockfd);
    return 0;
}

【源码免费下载链接】:https://renmaiwang.cn/s/jmsue 卷积神经网络(Convolutional Neural Networks, CNN)是一种深度学习模型,在图像处理和计算机视觉领域具有重要应用价值。通过MATLAB这一强大的工具平台,我们可以方便地实现CNN模型的构建、训练与优化过程。该压缩包中的MATLAB代码提供了一个完整的CNN实例,用户可以直接运行并观察其工作原理。理解CNN的基本结构是掌握其核心功能的关键。CNN通常由卷积层、池化层、全连接层以及激活函数等主要组件构成。具体来说,卷积层通过使用卷积核对输入图像进行扫描操作,提取图像中的特征信息;池化层则能够有效降低数据维度的同时减少计算量,并保留关键的视觉信息特征;全连接层负责将之前提取的特征信号映射到目标任务(如分类或回归)所需的输出结果空间中。此外,在MATLAB环境下,我们可以通过`deepLearningNetwork`函数轻松创建一个CNN模型架构。具体步骤包括:首先定义网络结构参数,例如卷积层的数量、尺寸以及激活函数类型等;其次设计完整的网络层次结构,并配置相关的超参数设置;最后利用提供的训练数据对模型进行优化和调参。在实际操作中,用户需要准备并整理好适合CNN处理的高质量图像数据集,并对其进行预处理工作,如归一化、裁剪或翻转等;接着可以使用MATLAB内置的数据导入与管理工具(如`imageDatastore`)来简化数据加载流程;最后通过设置合适的训练选项参数和执行训练过程,使模型能够自动学习并提取具有判别性的特征。在模型训练完成后,用户可以通过调用`classify`或`predict`函数对测试集中的图像进行分类预测,并评估模型的性能表现。值得注意的是,在这个压缩包中提供的CNN代码实例可能包含了从数据准备到模型部署的完整流程,其中包括了可视化、超参数调整等功能模
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值