C/C++轻量级并发TCP服务器框架Zinx-框架开发001: 读取标准输入,回显到标准输出

news/2024/7/7 19:03:48

文章目录

  • 完整代码实现参考-非项目使用
  • 项目使用的代码 - 乱-但是思路与上面的相同
    • 创建Kernel类
    • 添加删除修改epoll,才能写run方法
    • 创建stdin_Channel类
    • 在Kernel类中实现run方法

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

完整代码实现参考-非项目使用

#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/epoll.h>
#include <iostream>
#include <string>
using namespace std;

///stdin_channel类
class stdin_channel{
public:
    bool ReadFd(string &_input)
    {
        cin >> _input;
    }
};

///zinx_kernel类
class zinx_kernel{
    stdin_channel m_channel;
public:
    int iEpollFd;
    bool Add_Channel(stdin_channel &_channel)
    {
        bool bRet = false;

        struct epoll_event stEvent;
        stEvent.events = EPOLLIN;
        stEvent.data.ptr = &_channel;

        if (0 == epoll_ctl(iEpollFd, EPOLL_CTL_ADD, 0, &stEvent))
        {
            m_channel = _channel;
            bRet = true;
        }


        return bRet;
    }
    void Del_Channel(stdin_channel &_channel)
    {
        epoll_ctl(iEpollFd, EPOLL_CTL_DEL, 0, NULL);
    }
    bool run()
    {
        int iEpollRet = -1;

        for (;;)
        {
            struct epoll_event atmpEvent[100];
            iEpollRet = epoll_wait(iEpollFd, atmpEvent, 100, -1);
            if (-1 == iEpollRet)
            {
                if (EINTR == errno)
                {
                    continue;
                }
                else
                {
                    break;

                }

            }
            for (int i = 0; i < iEpollRet; i++)
            {
                stdin_channel *poChannel = static_cast<stdin_channel *>(atmpEvent[i].data.ptr);
                if (0 != (EPOLLIN & atmpEvent[i].events))
                {
                    string input;
                    poChannel->ReadFd(input);
                    cout << input <<endl;
                }

            }
        }


    }
};


///主函数
int main()
{
    zinx_kernel z;
    stdin_channel s;
    z.iEpollFd = epoll_create(1);
    z.Add_Channel(s);
    z.run();

}

项目使用的代码 - 乱-但是思路与上面的相同

Zinxkernel类中引入Channel类

定义一个channel对象,并设置get和set方法。

在stdinChannel类中实现一个ReadFd方法。

创建Kernel类

定义一个channel对象,并设置get和set方法。
但是set方法不适用epoll,应该是添加通道到epoll里,所以使用Addchannel

#pragma once

#include "stdin_channel.h"
#include "Ichannel.h"

class zinxkernel
{
	stdin_channel *m_channel = nullptr;

	zinxkernel();
	virtual ~zinxkernel();
	static zinxkernel kernel;
public:
	void run();

// 删除set方法
	void AddChannel(Ichannel *_pChannel);
	void DelChannel(Ichannel *_pChannel);
	void ModChannel_AddOut(Ichannel *_pChannel);
	void ModChannel_DelOut(Ichannel *_pChannel);

	stdin_channel *GetChannel()
	{
		return m_channel;
	}
	static zinxkernel &GetInstance()
	{
		return kernel;
	}
};

添加删除修改epoll,才能写run方法

void zinxkernel::AddChannel(Ichannel * _pChannel)
{
	if (true == _pChannel->init())
	{
		//将参数和文件描述符0关联起来(epoll_ctl)
		struct epoll_event stEvent;
		stEvent.events = EPOLLIN;
		stEvent.data.ptr = _pChannel;

		epoll_ctl(m_epollFd, EPOLL_CTL_ADD, _pChannel->GetFd(), &stEvent);
	}
}

void zinxkernel::DelChannel(Ichannel * _pChannel)
{
	epoll_ctl(m_epollFd, EPOLL_CTL_DEL, _pChannel->GetFd(), NULL);
	_pChannel->fini();
}

void zinxkernel::ModChannel_AddOut(Ichannel * _pChannel)
{
	struct epoll_event stEvent;
	stEvent.events = EPOLLIN | EPOLLOUT;
	stEvent.data.ptr = _pChannel;
	epoll_ctl(m_epollFd, EPOLL_CTL_MOD, _pChannel->GetFd(), &stEvent);
}

void zinxkernel::ModChannel_DelOut(Ichannel * _pChannel)
{
	struct epoll_event stEvent;
	stEvent.events = EPOLLIN;
	stEvent.data.ptr = _pChannel;
	epoll_ctl(m_epollFd, EPOLL_CTL_MOD, _pChannel->GetFd(), &stEvent);
}

创建stdin_Channel类

std::string stdin_channel::ReadFd()
{
	std::string ret;
	std::cin >> ret;
	return ret;
}

在Kernel类中实现run方法

1 等输入epoll
在哪里创建epoll fd?
在kernel的构造函数中创建。

zinxkernel::zinxkernel()
{
	int fd = epoll_create(1);
	if (fd >= 0)
	{
		m_epollFd = fd;
	}
}

zinxkernel::~zinxkernel()
{
	if (-1 != m_epollFd)
	{
		close(m_epollFd);
	}
}

等输入

		struct epoll_event astEvents[200];
		int ready_count = epoll_wait(m_epollFd, astEvents, 200, -1);
		if (0 == ready_count)
		{
			if (EINTR == errno)
			{
				continue;
			}
		}

2 调用输出通道的读取函数

		//2调用通道的读取函数或写出函数
		for (int i = 0; i < ready_count; i++)
		{
			if (0 != (astEvents[i].events & EPOLLIN))
			{
	// 3 回显到标准输出
				cout<<xxxxx
			}
		}
int main()
{
	stdin_channel in_channel;

	zinxkernel &kernel = zinxkernel::GetInstance();
	kernel.AddChannel(&in_channel);

	kernel.run();
}

http://lihuaxi.xjx100.cn/news/1790856.html

相关文章

springboot开启Redis缓存支持

开启缓存支持&#xff0c;只需要继承CachingConfigurerSupport 即可。代码如下&#xff1a; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; impo…

Webpack Bundle Analyzer包分析器

当我们需要分析打包文件dist里哪些资源可以进一步优化时&#xff0c;就可以使用包分析器插件webpack-bundle-analyzer。NPM上的介绍是使用交互式可缩放树图可视化 webpack 输出文件的大小。 我的是vue2项目。 1、webpack-bundle-analyzer插件的安装 $ npm install --save-dev…

Kerberos认证系统

文章目录 前提知识原理第一次对话第二次对话第三次对话 总结发现 前提知识 KDC&#xff1a;由AS、TGS&#xff0c;还有一个Kerberos Database组成。 Kerberos Database用来存储用户的密码或者其他所有信息&#xff0c;请求的时候需要到数据库中查找。 AS&#xff1a;为客户端提…

分库分表之后,主键ID如何处理?

前言 当关系型数据库数据量过大时&#xff0c;通常会采用分库分表降低数据库查表压力。分库分表有多种&#xff0c;有分一个库多张分表额&#xff0c;有分多个库多张表的。一般分库分表使用ShardingSphere分表&#xff0c;建分片键等。但是分库分表之后&#xff0c;主键ID如何处…

【nlp】2.2 传统RNN模型

传统RNN模型 1 传统RNN模型1.1 RNN结构分析1.2 使用Pytorch构建RNN模型1.3 传统RNN优缺点1 传统RNN模型 1.1 RNN结构分析 结构解释图: 内部结构分析: 我们把目光集中在中间的方块部分, 它的输入有两部分, 分别是h(t-1)以及x(t), 代表上一时间步的隐层输出, 以及此时间步的…

大数据知识图谱项目——基于知识图谱的电影问答系统(超详细讲解及源码)

大数据知识图谱项目——基于知识图谱的电影问答系统&#xff08;超详细讲解及源码&#xff09; 一、项目概述 知识图谱是将知识连接起来形成的一个网络。由节点和边组成&#xff0c;节点是实体&#xff0c;边是两个实体的关系&#xff0c;节点和边都可以有属性。知识图谱除了…

深入理解JVM虚拟机第二十五篇:详解JVM方法的绑定机制静态绑定和动态绑定,早期绑定晚期绑定,并编写代码从字节码角度证明这件事情

大神链接&#xff1a;作者有幸结识技术大神孙哥为好友&#xff0c;获益匪浅。现在把孙哥视频分享给大家。 孙哥链接&#xff1a;孙哥个人主页 作者简介&#xff1a;一个颜值99分&#xff0c;只比孙哥差一点的程序员 本专栏简介&#xff1a;话不多说&#xff0c;让我们一起干翻J…

线程相关问题

多线程 计算机在同一时间可以执行多个线程 并行 多个事情在同一时间点内发生&#xff0c;并行的发生是不会抢占资源的 并发 多个事情在一段时间内同时发生&#xff0c;并发的产生会抢占资源 多线程的好处 如果为单线程计算机一次只能处理一个线程&#xff0c;那么当处理的线程需…