代码拉取完成,页面将自动刷新
#pragma once
// 模板方法模式,套接字的套路都是一样的
// 使用父类提供的统一的构建套接字的方法,立马把子类实现的具体方法按顺序全部调出来,这种模式叫做模板方法模式
// 子类实现细节,父类做宏观调用,这就叫做模板方法模式
#include <iostream>
#include <string>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdlib>
#include <strings.h>
#include "Log.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"
namespace SocketModule
{
using namespace LogModule;
class Socket;
using SockPtr = std::shared_ptr<Socket>;
// 基类,规定创建Socket的方法
// 提供一个/若干个/固定模式的socket的方法
class Socket
{
public:
virtual ~Socket() = default;
virtual void SocketOrDie() = 0;
virtual void SetSocketOpt() = 0;
virtual bool BindOrDie(int port) = 0;
virtual bool ListenOrDie() = 0;
virtual SockPtr Accepter(InetAddr *client) = 0;
virtual void Close() = 0;
virtual int Recv(std::string *out) = 0;
virtual int Send(const std::string &in) = 0;
virtual int Fd() = 0;
// 其他方法,需要的时候再加
void BulidTcpSocketMethod(int port)
{
SocketOrDie();
SetSocketOpt();
BindOrDie(port);
ListenOrDie();
}
// #ifdef WIN
// // 提供一个创建listensockfd的固定方法
// void BulidTcpSocket()
// {
// SocketOrDie();
// SetSocketOpt();
// BindOrDie();
// ListenOrDie();
// }
// // 提供一个创建udpsockfd的固定方法
// void BulidUdpSocket()
// {}
// #else // Linux
// // 提供一个创建listensockfd的固定方法
// void BulidTcpSocket()
// {
// SocketOrDie();
// SetSocketOpt();
// BindOrDie();
// ListenOrDie();
// }
// // 提供一个创建udpsockfd的固定方法
// void BulidUdpSocket()
// {}
// #endif
};
// class UdpSocket : public Socket
// {
// public:
// virtual ~UdpSocket()
// {}
// virtual int SocketOrDie() = 0;
// virtual void SetSocketOpt() = 0;
// virtual bool BindOrDie(int listendockfd) = 0;
// virtual bool ListenOrDie(int listendockfd) = 0;
// virtual int Accepter(int listendockfd) = 0;
// virtual void Close(int fd) = 0;
// private:
// };
class TcpSocket : public Socket
{
public:
TcpSocket() : _sockfd(gdefaultsockfd)
{
}
TcpSocket(int sockfd) : _sockfd(sockfd)
{}
virtual ~TcpSocket()
{
}
virtual void SocketOrDie() override
{
_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
if (_sockfd < 0)
{
LOG(LogLevel::ERROR) << "socket error";
exit(SOCKET_ERR);
}
LOG(LogLevel::DEBUG) << "socket create success:" << _sockfd;
}
virtual void SetSocketOpt() override
{
}
virtual bool BindOrDie(int port) override
{
if (_sockfd == gdefaultsockfd)
return false;
// struct sockaddr_in local;
// bzero(&local,sizeof(local));
InetAddr addr(port);
int n = ::bind(_sockfd, addr.NetAddr(), addr.NetAddrLen());
if (n < 0)
{
LOG(LogLevel::ERROR) << "bind error";
exit(SOCKET_ERR);
}
LOG(LogLevel::DEBUG) << "bind create success:" << _sockfd;
return true;
}
virtual bool ListenOrDie() override
{
if(_sockfd == gdefaultsockfd)
return false;
int n = ::listen(_sockfd,gbacklog);
if(n < 0)
{
LOG(LogLevel::ERROR) << "listen error";
exit(LISTEN_ERR);
}
LOG(LogLevel::DEBUG) << "listen create successL: " << _sockfd;
return true;
}
// 1.文件描述符 2.client info(信息)
virtual SockPtr Accepter(InetAddr *client) override
{
if(!client) return nullptr;
struct sockaddr_in peer;
socklen_t len = sizeof(peer);
int newsockfd = ::accept(_sockfd,CONV(&peer),&len);
if(newsockfd < 0)
{
LOG(LogLevel::WARNING) << "accept error";
return nullptr;
}
client->SetAddr(peer,len);
return std::make_shared<TcpSocket>(newsockfd);
}
virtual void Close() override
{
if(_sockfd == gdefaultsockfd)
return;
::close(_sockfd);
}
virtual int Recv(std::string *out) override
{
char buffer[1024*8];
auto size = ::recv(_sockfd,buffer,sizeof(buffer)-1,0);
if(size > 0)
{
buffer[size] = 0;
*out = buffer;
}
return size;
}
virtual int Send(const std::string &in) override
{
auto size = ::send(_sockfd,in.c_str(),in.size(),0);
(void)size;
return size;
}
virtual int Fd() override
{
return _sockfd;
}
private:
int _sockfd;
};
// test
//int main()
// {
// Socket *sk = new TcpSocket();
// sk->BulidTcpSocket(8080);
// }
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。