Make Socket noncopyable, without inheritance.

This commit is contained in:
Relintai 2022-02-09 23:48:12 +01:00
parent 0e6ad2d135
commit 94fd22eee9

View File

@ -16,7 +16,6 @@
#pragma once #pragma once
#include <trantor/utils/NonCopyable.h>
#include "core/net/inet_address.h" #include "core/net/inet_address.h"
#include <trantor/utils/Logger.h> #include <trantor/utils/Logger.h>
#include <string> #include <string>
@ -25,135 +24,133 @@
#endif #endif
#include <fcntl.h> #include <fcntl.h>
namespace trantor namespace trantor {
{ class Socket {
class Socket : NonCopyable
{ protected:
public: // NonCopyable
static int createNonblockingSocketOrDie(int family) Socket(const Socket &) = delete;
{ Socket &operator=(const Socket &) = delete;
// some uncopyable classes maybe support move constructor....
Socket(Socket &&) noexcept(true) = default;
Socket &operator=(Socket &&) noexcept(true) = default;
public:
static int createNonblockingSocketOrDie(int family) {
#ifdef __linux__ #ifdef __linux__
int sock = ::socket(family, int sock = ::socket(family,
SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
IPPROTO_TCP); IPPROTO_TCP);
#else #else
int sock = static_cast<int>(::socket(family, SOCK_STREAM, IPPROTO_TCP)); int sock = static_cast<int>(::socket(family, SOCK_STREAM, IPPROTO_TCP));
setNonBlockAndCloseOnExec(sock); setNonBlockAndCloseOnExec(sock);
#endif #endif
if (sock < 0) if (sock < 0) {
{ LOG_SYSERR << "sockets::createNonblockingOrDie";
LOG_SYSERR << "sockets::createNonblockingOrDie"; exit(1);
exit(1); }
} LOG_TRACE << "sock=" << sock;
LOG_TRACE << "sock=" << sock; return sock;
return sock; }
}
static int getSocketError(int sockfd) static int getSocketError(int sockfd) {
{ int optval;
int optval; socklen_t optlen = static_cast<socklen_t>(sizeof optval);
socklen_t optlen = static_cast<socklen_t>(sizeof optval);
#ifdef _WIN32 #ifdef _WIN32
if (::getsockopt( if (::getsockopt(
sockfd, SOL_SOCKET, SO_ERROR, (char *)&optval, &optlen) < 0) sockfd, SOL_SOCKET, SO_ERROR, (char *)&optval, &optlen) < 0)
#else #else
if (::getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0) if (::getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0)
#endif #endif
{ {
return errno; return errno;
} } else {
else return optval;
{ }
return optval; }
}
}
static int connect(int sockfd, const InetAddress &addr) static int connect(int sockfd, const InetAddress &addr) {
{ if (addr.isIpV6())
if (addr.isIpV6()) return ::connect(sockfd,
return ::connect(sockfd, addr.getSockAddr(),
addr.getSockAddr(), static_cast<socklen_t>(
static_cast<socklen_t>( sizeof(struct sockaddr_in6)));
sizeof(struct sockaddr_in6))); else
else return ::connect(sockfd,
return ::connect(sockfd, addr.getSockAddr(),
addr.getSockAddr(), static_cast<socklen_t>(
static_cast<socklen_t>( sizeof(struct sockaddr_in)));
sizeof(struct sockaddr_in))); }
}
static bool isSelfConnect(int sockfd); static bool isSelfConnect(int sockfd);
explicit Socket(int sockfd) : sockFd_(sockfd) explicit Socket(int sockfd) :
{ sockFd_(sockfd) {
} }
~Socket(); ~Socket();
/// abort if address in use /// abort if address in use
void bindAddress(const InetAddress &localaddr); void bindAddress(const InetAddress &localaddr);
/// abort if address in use /// abort if address in use
void listen(); void listen();
int accept(InetAddress *peeraddr); int accept(InetAddress *peeraddr);
void closeWrite(); void closeWrite();
int read(char *buffer, uint64_t len); int read(char *buffer, uint64_t len);
int fd() int fd() {
{ return sockFd_;
return sockFd_; }
} static struct sockaddr_in6 getLocalAddr(int sockfd);
static struct sockaddr_in6 getLocalAddr(int sockfd); static struct sockaddr_in6 getPeerAddr(int sockfd);
static struct sockaddr_in6 getPeerAddr(int sockfd);
/// ///
/// Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm). /// Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm).
/// ///
void setTcpNoDelay(bool on); void setTcpNoDelay(bool on);
/// ///
/// Enable/disable SO_REUSEADDR /// Enable/disable SO_REUSEADDR
/// ///
void setReuseAddr(bool on); void setReuseAddr(bool on);
/// ///
/// Enable/disable SO_REUSEPORT /// Enable/disable SO_REUSEPORT
/// ///
void setReusePort(bool on); void setReusePort(bool on);
/// ///
/// Enable/disable SO_KEEPALIVE /// Enable/disable SO_KEEPALIVE
/// ///
void setKeepAlive(bool on); void setKeepAlive(bool on);
int getSocketError(); int getSocketError();
protected: protected:
int sockFd_; int sockFd_;
public: public:
// taken from muduo // taken from muduo
static void setNonBlockAndCloseOnExec(int sockfd) static void setNonBlockAndCloseOnExec(int sockfd) {
{
#ifdef _WIN32 #ifdef _WIN32
// TODO how to set FD_CLOEXEC on windows? is it necessary? // TODO how to set FD_CLOEXEC on windows? is it necessary?
u_long arg = 1; u_long arg = 1;
auto ret = ioctlsocket(sockfd, (long)FIONBIO, &arg); auto ret = ioctlsocket(sockfd, (long)FIONBIO, &arg);
if (ret) if (ret) {
{ LOG_ERROR << "ioctlsocket error";
LOG_ERROR << "ioctlsocket error"; }
}
#else #else
// non-block // non-block
int flags = ::fcntl(sockfd, F_GETFL, 0); int flags = ::fcntl(sockfd, F_GETFL, 0);
flags |= O_NONBLOCK; flags |= O_NONBLOCK;
int ret = ::fcntl(sockfd, F_SETFL, flags); int ret = ::fcntl(sockfd, F_SETFL, flags);
// TODO check // TODO check
// close-on-exec // close-on-exec
flags = ::fcntl(sockfd, F_GETFD, 0); flags = ::fcntl(sockfd, F_GETFD, 0);
flags |= FD_CLOEXEC; flags |= FD_CLOEXEC;
ret = ::fcntl(sockfd, F_SETFD, flags); ret = ::fcntl(sockfd, F_SETFD, flags);
// TODO check // TODO check
(void)ret; (void)ret;
#endif #endif
} }
}; };
} // namespace trantor } // namespace trantor