mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2024-11-14 04:57:21 +01:00
Make Socket noncopyable, without inheritance.
This commit is contained in:
parent
0e6ad2d135
commit
94fd22eee9
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user