X Tutup
#include "Socket.h" namespace HttpServer { bool Socket::Startup() { #ifdef WIN32 unsigned short version = MAKEWORD(2, 2); ::WSADATA wsaData = {0}; return 0 == ::WSAStartup(version, &wsaData); #elif POSIX return true; #else #error "Undefine platform" #endif } bool Socket::Cleanup() { #ifdef WIN32 return 0 == ::WSACleanup(); #elif POSIX return true; #else #error "Undefine platform" #endif } int Socket::getLastError() { #ifdef WIN32 return ::WSAGetLastError(); #elif POSIX return errno; #else #error "Undefine platform" #endif } Socket::Socket(): socket_handle(~0) { } Socket::Socket(const System::native_socket_type fd) : socket_handle(fd) { } Socket::Socket(const Socket &obj) : socket_handle(obj.socket_handle) { } Socket::Socket(Socket &&obj) : socket_handle(obj.socket_handle) { obj.socket_handle = ~0; } bool Socket::open() { this->close(); this->socket_handle = ::socket(AF_INET, SOCK_STREAM, 0); return this->is_open(); } bool Socket::close() { if (this->is_open() ) { #ifdef WIN32 const int result = ::closesocket(this->socket_handle); #elif POSIX const int result = ::close(this->socket_handle); #else #error "Undefine platform" #endif if (0 == result) { this->socket_handle = ~0; return true; } } return false; } bool Socket::bind(const int port) const { const ::sockaddr_in sock_addr = { AF_INET, htons(port), ::htonl(INADDR_ANY), 0 }; return 0 == ::bind(this->socket_handle, reinterpret_cast(&sock_addr), sizeof(sockaddr_in) ); } bool Socket::listen() const { return 0 == ::listen(this->socket_handle, SOMAXCONN); } Socket Socket::accept() const { #ifdef WIN32 System::native_socket_type client_socket = ::accept(this->socket_handle, static_cast(nullptr), static_cast(nullptr) ); #elif POSIX System::native_socket_type client_socket = ::accept(this->socket_handle, static_cast(nullptr), static_cast(nullptr) ); #else #error "Undefine platform" #endif return Socket(client_socket); } Socket Socket::nonblock_accept() const { System::native_socket_type client_socket = ~0; #ifdef WIN32 WSAPOLLFD event = { this->socket_handle, POLLRDNORM, 0 }; if (1 == ::WSAPoll(&event, 1, ~0) && event.revents & POLLRDNORM) { client_socket = ::accept(this->socket_handle, static_cast(nullptr), static_cast(nullptr) ); } #elif POSIX struct ::pollfd event = { this->socket_handle, POLLIN, 0 }; if (1 == ::poll(&event, 1, ~0) && event.revents & POLLIN) { client_socket = ::accept(this->socket_handle, static_cast(nullptr), static_cast(nullptr) ); } #else #error "Undefine platform" #endif return Socket(client_socket); } Socket Socket::nonblock_accept(const std::chrono::milliseconds &timeout) const { System::native_socket_type client_socket = ~0; #ifdef WIN32 WSAPOLLFD event = { this->socket_handle, POLLRDNORM, 0 }; if (1 == ::WSAPoll(&event, 1, timeout.count() ) && event.revents & POLLRDNORM) { client_socket = ::accept(this->socket_handle, static_cast(nullptr), static_cast(nullptr) ); } #elif POSIX struct ::pollfd event = { this->socket_handle, POLLIN, 0 }; if (1 == ::poll(&event, 1, timeout.count() ) && event.revents & POLLIN) { client_socket = ::accept(this->socket_handle, static_cast(nullptr), static_cast(nullptr) ); } #else #error "Undefine platform" #endif return Socket(client_socket); } bool Socket::shutdown() const { if (is_open() ) { #ifdef WIN32 return 0 == ::shutdown(this->socket_handle, SD_BOTH); #elif POSIX return 0 == ::shutdown(this->socket_handle, SHUT_RDWR); #else #error "Undefine platform" #endif } return false; } bool Socket::nonblock(const bool isNonBlock) const { #ifdef WIN32 unsigned long value = isNonBlock; return 0 == ::ioctlsocket(this->socket_handle, FIONBIO, &value); #elif POSIX return ~0 != ::fcntl(this->socket_handle, F_SETFL, isNonBlock ? O_NONBLOCK : O_SYNC); #else #error "Undefine platform" #endif } /* bool Socket::is_nonblock() const { #ifdef WIN32 #elif POSIX const int flags = ::fcntl(socket_handle, F_GETFL, 0); return (flags != ~0) && (flags & O_NONBLOCK); #else #error "Undefine platform" #endif } */ bool Socket::tcp_nodelay(const bool nodelay) const { #ifdef WIN32 int flags = nodelay ? 1 : 0; return 0 == setsockopt(this->socket_handle, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&flags), sizeof(flags) ); #elif POSIX int flags = nodelay ? 1 : 0; return 0 == setsockopt(this->socket_handle, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags) ); #else #error "Undefine platform" #endif } long Socket::recv(std::vector &buf) const { #ifdef WIN32 return ::recv(this->socket_handle, buf.data(), buf.size(), 0); #elif POSIX return ::recv(this->socket_handle, buf.data(), buf.size(), 0); #else #error "Undefine platform" #endif } long Socket::nonblock_recv(std::vector &buf, const std::chrono::milliseconds &timeout) const { long recv_len = ~0; #ifdef WIN32 WSAPOLLFD event = { this->socket_handle, POLLRDNORM, 0 }; if (1 == ::WSAPoll(&event, 1, timeout.count() ) && event.revents & POLLRDNORM) { recv_len = ::recv(this->socket_handle, buf.data(), buf.size(), 0); } #elif POSIX struct ::pollfd event = { this->socket_handle, POLLIN, 0 }; if (1 == ::poll(&event, 1, timeout.count() ) && event.revents & POLLIN) { recv_len = ::recv(this->socket_handle, buf.data(), buf.size(), 0); } #else #error "Undefine platform" #endif return recv_len; } static long send_all(const System::native_socket_type socket_handle, const void *data, const size_t length) { size_t total = 0; while (total < length) { const long send_size = ::send(socket_handle, reinterpret_cast(data) + total, length - total, 0); if (send_size < 0) { return send_size; } total += send_size; } return total; } long Socket::send(const std::string &buf) const { return send_all(this->socket_handle, buf.data(), buf.length() ); } long Socket::send(const std::vector &buf, const size_t length) const { return send_all(this->socket_handle, buf.data(), length); } static long nonblock_send_all(const System::native_socket_type socket_handle, const void *data, const size_t length, const std::chrono::milliseconds &timeout) { size_t total = 0; #ifdef WIN32 WSAPOLLFD event = { socket_handle, POLLWRNORM, 0 }; while (total < length) { if (1 == ::WSAPoll(&event, 1, timeout.count() ) && event.revents & POLLWRNORM) { const long send_size = ::send(socket_handle, reinterpret_cast(data) + total, length - total, 0); if (send_size < 0) { return send_size; } total += send_size; } else { return -1; } } #elif POSIX struct ::pollfd event = { socket_handle, POLLOUT, 0 }; while (total < length) { if (1 == ::poll(&event, 1, timeout.count() ) && event.revents & POLLOUT) { const long send_size = ::send(socket_handle, reinterpret_cast(data) + total, length - total, 0); if (send_size < 0) { return send_size; } total += send_size; } else { return -1; } } #else #error "Undefine platform" #endif return total; } long Socket::nonblock_send(const std::string &buf, const std::chrono::milliseconds &timeout) const { return nonblock_send_all(this->socket_handle, buf.data(), buf.length(), timeout); } long Socket::nonblock_send(const std::vector &buf, const size_t length, const std::chrono::milliseconds &timeout) const { return nonblock_send_all(this->socket_handle, buf.data(), length, timeout); } void Socket::nonblock_send_sync() const { #ifdef WIN32 WSAPOLLFD event = { this->socket_handle, POLLWRNORM, 0 }; ::WSAPoll(&event, 1, ~0); #elif POSIX struct ::pollfd event = { this->socket_handle, POLLOUT, 0 }; ::poll(&event, 1, ~0); #else #error "Undefine platform" #endif } Socket &Socket::operator=(const Socket &obj) { this->socket_handle = obj.socket_handle; return *this; } bool Socket::operator ==(const Socket &obj) const { return this->socket_handle == obj.socket_handle; } bool Socket::operator !=(const Socket &obj) const { return this->socket_handle != obj.socket_handle; } };
X Tutup