Ai
1 Star 0 Fork 0

Bart/笔记仓库

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
PollServer.hpp 5.68 KB
一键复制 编辑 原始数据 按行查看 历史
Bart 提交于 2024-06-22 23:27 +08:00 . poll相关接口测试
#pragma once
#include <iostream>
#include <string>
#include <poll.h>
#include <memory>
#include "Socket.hpp"
#include "Log.hpp"
using namespace Net_Work;
const static int gdefaultport = 8888;
const static int gbacklog = 8;
const int gnum = 1024;
class PollServer
{
void HandlerEvent()
{
for (int i = 0; i < _num; i++)
{
if (_rfds[i].fd == -1)
continue;
int fd = _rfds[i].fd;
short revents = _rfds[i].events;
if (revents & POLLIN) // 判断是否是读准备就绪
{
if (fd == _listensock->GetSockFd()) // 监听fd建立新链接(链接就绪)
{
lg.LogMessage(Info, "get a new link\n");
std::string clientip;
uint16_t clientport;
// 这里已经不会再阻塞了,select已经检测到了listensock已经就绪了!!!
int sock = _listensock->AcceptConnection(&clientip, &clientport);
if (!sock)
{
lg.LogMessage(Error, "accept error\n");
return;
}
lg.LogMessage(Info, "get a client, client info is# %s: %d, fd: %d\n", clientip.c_str(), clientport, sock);
// 这里已经获取连接成功
// 连接已经建立好,不能确定对方是否发数据
// read?write?绝对不能!!!read 底层数据是否就绪时不确定的!谁清楚fd上面是否有读事件呢?select!
// 新链接fd到来的时候,要把新的fd, 想办法交给select托管 -- 只需要添加到数组_rfds_array中即可
int pos = 0;
for (; pos < _num; pos++)
{
if (_rfds[pos].fd == -1)
{
_rfds[pos].fd = sock;
_rfds[pos].events = POLLIN;
lg.LogMessage(Info, "get a new link, fd is : %d\n", sock);
break;
}
}
// 数组满了
if (pos == _num)
{
// 1.扩容
// 2.关闭
close(sock);
lg.LogMessage(Warning, "server is full...!\n");
}
}
else // 普通的读事件就绪
{
// 这里读取已经不会卡住
char buffer[1024];
ssize_t n = recv(fd, buffer, sizeof(buffer)-1, 0);
if (n > 0)
{
lg.LogMessage(Info, "client say# %s\n", buffer);
std::string message = ": 你好呀,少年";
message += buffer;
send(fd, message.c_str(), message.size(), 0);
}
else
{
lg.LogMessage(Warning, "client quit, maybe close or error, close fd : %d\n", fd);
close(fd);
// 取消poll关系
_rfds[i].fd = -1;
_rfds[i].events = 0;
_rfds[i].revents = 0;
}
}
}
}
}
public:
PollServer(int port = gdefaultport) : _port(port), _listensock(new TcpSocket()), _num(gnum)
{
}
void InitServer()
{
// 创建套接字+bind
_listensock->BuildListenSocketMethod(_port, gbacklog);
_rfds = new struct pollfd[_num];
for (int i = 0; i < _num; i++)
{
_rfds[i].fd = -1;
_rfds[i].events = 0;
_rfds[i].revents = 0;
}
// 最开始只有一个文件描述符
_rfds[0].fd = _listensock->GetSockFd();
_rfds[0].events = POLLIN; // 读
}
void Loop()
{
_running = true;
while (_running)
{
// 设定时间
int timeout = 1000;// 0 或 -1(阻塞式)
// PrintDebug();
// 最大的fd要能够动态更新
// rfds本质是一个输入输出型参数,rfds是在select调用返回的时候,不断被修改,所以,每次都要重置
int n = poll(_rfds, _num, timeout); // 返回准备就绪的fd,并设置到rfds中(也可能是之前设设置的fd准备就绪并返回)
switch (n)
{
case 0:
lg.LogMessage(Info, "poll timeout...\n");
break;
case -1:
lg.LogMessage(Error, "poll error!!!\n");
break;
default:
// 正常的就绪的fd
// 第一次等待client建立连接
lg.LogMessage(Info, "select success, begin event handler\n");
HandlerEvent(); // 准备就绪的fd集合(读集合) _rfds_array: 3,4,5,6,7,8,9,10 -> rfds: 4,5,6
break;
}
}
_running = false;
}
void Stop()
{
_running = false;
}
void PrintDebug()
{
std::cout << "current select rfds list is : ";
for (int i = 0; i < _num; i++)
{
if (_rfds[i].fd == -1)
continue;
else
std::cout << _rfds[i].fd << " ";
}
std::cout << std::endl;
}
~PollServer()
{
delete[] _rfds;
}
private:
std::unique_ptr<Socket> _listensock;
int _port;
int _running;
struct pollfd *_rfds;
int _num;
};
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/lf_yzy/note-warehouse.git
git@gitee.com:lf_yzy/note-warehouse.git
lf_yzy
note-warehouse
笔记仓库
master

搜索帮助