文章目录
Socket
代码语言:javascript
复制#pragma once
#include "nocopyable.hpp"
class InetAddress;
//封装sockfd
class Socket:public nocpoyable{
public:
explicit Socket(int sockfd)
:sockfd_(sockfd)
{}
~Socket();
int fd(){ return sockfd_;}
void bindAddress(const InetAddress &localaddr);
void listen();
int accept(InetAddress* peeraddr);
void setReuseAddr(bool on);
void setReusePort(bool on);
private:
int sockfd_;
};
代码语言:javascript
复制#include "socket.hpp"
#include "InetAddr.hpp"
#include "logger.hpp"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
Socket::~Socket(){
close(sockfd_);
}
void Socket::bindAddress(const InetAddress &localaddr){
if (0 == bind(sockfd_, (sockaddr *)localaddr.getSockAddr(), sizeof(sockaddr_in))){
LOG_FATAL("sockets::bindOrDie");
}
}
void Socket::listen(){
if (0 != ::listen(sockfd_, 1024)){
LOG_FATAL("sockets::listenOrDie");
}
}
int Socket::accept(InetAddress *peeraddr){
sockaddr_in addr;
socklen_t len;
bzero(&addr, sizeof(sockaddr_in));
int confd = ::accept(sockfd_, (sockaddr *)&addr, &len);
if (confd >= 0){
peeraddr->setSockAddr(addr);
}
return confd;
}
void Socket::setReuseAddr(bool on){
int optval = on ? 1 : 0;
::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR,
&optval, static_cast<socklen_t>(sizeof optval));
}
void Socket::setReusePort(bool on){
int optval = on ? 1 : 0;
int ret = ::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEPORT,
&optval, static_cast<socklen_t>(sizeof optval));
if (ret < 0 && on){
LOG_FATAL("SO_REUSEPORT failed.");
}
}
Acceptor
代码语言:javascript
复制#pragma once
#include "nocopyable.hpp"
#include "channel.hpp"
#include "socket.hpp"
#include <functional>
class EventLoop;
class InetAddress;
class Accept : public nocpoyable
{
public:
using NewConnectionCallBack = std::function<void(int sockfd, const InetAddress &)>;
Accept(EventLoop *loop, const InetAddress &listenAddr, bool reuseport);
~Accept();
void setNewConnectionCallback(const NewConnectionCallBack &cb){
newConnectionCallback_ = cb;
}
void listen();
bool listening() const { return listening_; }
private:
void handleRead();
EventLoop *loop_; //mainloop
Socket acceptSocket_;
Channel acceptChannel_;
NewConnectionCallBack newConnectionCallback_;
bool listening_;
int idleFd_;
};
代码语言:javascript
复制#include "accept.hpp"
#include "logger.hpp"
//#include "eventloop.hpp"
#include "InetAddr.hpp"
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
static int createNonblcking(){
int sockfd = ::socket(AF_INET,SOCK_STREAM |SOCK_NONBLOCK,IPPROTO_TCP);
if(sockfd < 0){
LOG_FATAL("%s:%s:%d listen socket create err:%dn",__FILE__,__FUNCTION__,__LINE__,errno);
}
}
Accept::Accept(EventLoop *loop, const InetAddress &listenAddr, bool reuseport)
: loop_(loop),
acceptSocket_(createNonblcking()),
acceptChannel_(loop, acceptSocket_.fd()),
listening_(false),
idleFd_(::open("/dev/null", O_RDONLY | O_CLOEXEC))
{
acceptSocket_.setReuseAddr(true);
acceptSocket_.setReusePort(reuseport);
acceptSocket_.bindAddress(listenAddr);
//监听到有客户端连接,执行一个回调,甩给字loop
acceptChannel_.setReadCallback(std::bind(&Accept::handleRead, this));
}
Accept::~Accept()
{
acceptChannel_.disableAll();
acceptChannel_.remove();
::close(idleFd_);
}
void Accept::listen()
{
listening_ = true;
acceptSocket_.listen();
acceptChannel_.enableReading();
}
void Accept::handleRead(){
InetAddress peerAddr;
int connfd = acceptSocket_.accept(&peerAddr);
if (connfd >= 0){
if (newConnectionCallback_){
newConnectionCallback_(connfd, peerAddr);
}
else{
::close(connfd);
}
}
else{
LOG_ERROR("in Acceptor::handleRead");
if (errno == EMFILE){
::close(idleFd_);
idleFd_ = ::accept(acceptSocket_.fd(), NULL, NULL);
::close(idleFd_);
idleFd_ = ::open("/dev/null", O_RDONLY | O_CLOEXEC);
}
}
}