socketimpl.cpp
来自「很好用的网络封装库,不熟悉网络编程的人也可以使用。使用风格良好的标准c++编写。」· C++ 代码 · 共 881 行 · 第 1/2 页
CPP
881 行
{
#ifndef POCO_BROKEN_TIMEOUTS
#if defined(_WIN32)
int value = (int) timeout.totalMilliseconds();
setOption(SOL_SOCKET, SO_RCVTIMEO, value);
#else
setOption(SOL_SOCKET, SO_RCVTIMEO, timeout);
#endif
#else
_recvTimeout = timeout;
#endif
}
Poco::Timespan SocketImpl::getReceiveTimeout()
{
Timespan result;
#if defined(_WIN32)
int value;
getOption(SOL_SOCKET, SO_RCVTIMEO, value);
result = Timespan::TimeDiff(value)*1000;
#elif defined(POCO_BROKEN_TIMEOUTS)
result = _recvTimeout;
#else
getOption(SOL_SOCKET, SO_RCVTIMEO, result);
#endif
return result;
}
SocketAddress SocketImpl::address()
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
char buffer[SocketAddress::MAX_ADDRESS_LENGTH];
struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(buffer);
poco_socklen_t saLen = sizeof(buffer);
int rc = ::getsockname(_sockfd, pSA, &saLen);
if (rc == 0)
return SocketAddress(pSA, saLen);
else
error();
return SocketAddress();
}
SocketAddress SocketImpl::peerAddress()
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
char buffer[SocketAddress::MAX_ADDRESS_LENGTH];
struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(buffer);
poco_socklen_t saLen = sizeof(buffer);
int rc = ::getpeername(_sockfd, pSA, &saLen);
if (rc == 0)
return SocketAddress(pSA, saLen);
else
error();
return SocketAddress();
}
void SocketImpl::setOption(int level, int option, int value)
{
setRawOption(level, option, &value, sizeof(value));
}
void SocketImpl::setOption(int level, int option, unsigned value)
{
setRawOption(level, option, &value, sizeof(value));
}
void SocketImpl::setOption(int level, int option, unsigned char value)
{
setRawOption(level, option, &value, sizeof(value));
}
void SocketImpl::setOption(int level, int option, const IPAddress& value)
{
setRawOption(level, option, value.addr(), value.length());
}
void SocketImpl::setOption(int level, int option, const Poco::Timespan& value)
{
struct timeval tv;
tv.tv_sec = (long) value.totalSeconds();
tv.tv_usec = (long) value.useconds();
setRawOption(level, option, &tv, sizeof(tv));
}
void SocketImpl::setRawOption(int level, int option, const void* value, poco_socklen_t length)
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
int rc = ::setsockopt(_sockfd, level, option, reinterpret_cast<const char*>(value), length);
if (rc == -1) error();
}
void SocketImpl::getOption(int level, int option, int& value)
{
poco_socklen_t len = sizeof(value);
getRawOption(level, option, &value, len);
}
void SocketImpl::getOption(int level, int option, unsigned& value)
{
poco_socklen_t len = sizeof(value);
getRawOption(level, option, &value, len);
}
void SocketImpl::getOption(int level, int option, unsigned char& value)
{
poco_socklen_t len = sizeof(value);
getRawOption(level, option, &value, len);
}
void SocketImpl::getOption(int level, int option, Poco::Timespan& value)
{
struct timeval tv;
poco_socklen_t len = sizeof(tv);
getRawOption(level, option, &tv, len);
value.assign(tv.tv_sec, tv.tv_usec);
}
void SocketImpl::getOption(int level, int option, IPAddress& value)
{
char buffer[IPAddress::MAX_ADDRESS_LENGTH];
poco_socklen_t len = sizeof(buffer);
getRawOption(level, option, buffer, len);
value = IPAddress(buffer, len);
}
void SocketImpl::getRawOption(int level, int option, void* value, poco_socklen_t& length)
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
int rc = ::getsockopt(_sockfd, level, option, reinterpret_cast<char*>(value), &length);
if (rc == -1) error();
}
void SocketImpl::setLinger(bool on, int seconds)
{
struct linger l;
l.l_onoff = on ? 1 : 0;
l.l_linger = seconds;
setRawOption(SOL_SOCKET, SO_LINGER, &l, sizeof(l));
}
void SocketImpl::getLinger(bool& on, int& seconds)
{
struct linger l;
poco_socklen_t len = sizeof(l);
getRawOption(SOL_SOCKET, SO_LINGER, &l, len);
on = l.l_onoff != 0;
seconds = l.l_linger;
}
void SocketImpl::setNoDelay(bool flag)
{
int value = flag ? 1 : 0;
setOption(IPPROTO_TCP, TCP_NODELAY, value);
}
bool SocketImpl::getNoDelay()
{
int value;
getOption(IPPROTO_TCP, TCP_NODELAY, value);
return value != 0;
}
void SocketImpl::setKeepAlive(bool flag)
{
int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_KEEPALIVE, value);
}
bool SocketImpl::getKeepAlive()
{
int value;
getOption(SOL_SOCKET, SO_KEEPALIVE, value);
return value != 0;
}
void SocketImpl::setReuseAddress(bool flag)
{
int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_REUSEADDR, value);
}
bool SocketImpl::getReuseAddress()
{
int value;
getOption(SOL_SOCKET, SO_REUSEADDR, value);
return value != 0;
}
void SocketImpl::setReusePort(bool flag)
{
#ifdef SO_REUSEPORT
try
{
int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_REUSEPORT, value);
}
catch (IOException&)
{
// ignore error, since not all implementations
// support SO_REUSEPORT, even if the macro
// is defined.
}
#endif
}
bool SocketImpl::getReusePort()
{
#ifdef SO_REUSEPORT
int value;
getOption(SOL_SOCKET, SO_REUSEPORT, value);
return value != 0;
#else
return false;
#endif
}
void SocketImpl::setOOBInline(bool flag)
{
int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_OOBINLINE, value);
}
bool SocketImpl::getOOBInline()
{
int value;
getOption(SOL_SOCKET, SO_OOBINLINE, value);
return value != 0;
}
void SocketImpl::setBroadcast(bool flag)
{
int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_BROADCAST, value);
}
bool SocketImpl::getBroadcast()
{
int value;
getOption(SOL_SOCKET, SO_BROADCAST, value);
return value != 0;
}
void SocketImpl::setBlocking(bool flag)
{
int arg = flag ? 0 : 1;
ioctl(FIONBIO, arg);
_blocking = flag;
}
int SocketImpl::socketError()
{
int result;
getOption(SOL_SOCKET, SO_ERROR, result);
return result;
}
void SocketImpl::init(int af)
{
initSocket(af, SOCK_STREAM);
}
void SocketImpl::initSocket(int af, int type, int proto)
{
poco_assert (_sockfd == POCO_INVALID_SOCKET);
_sockfd = ::socket(af, type, proto);
if (_sockfd == POCO_INVALID_SOCKET)
error();
}
void SocketImpl::ioctl(int request, int& arg)
{
#if defined(_WIN32)
int rc = ioctlsocket(_sockfd, request, reinterpret_cast<u_long*>(&arg));
#else
int rc = ::ioctl(_sockfd, request, &arg);
#endif
if (rc != 0) error();
}
void SocketImpl::ioctl(int request, void* arg)
{
#if defined(_WIN32)
int rc = ioctlsocket(_sockfd, request, reinterpret_cast<u_long*>(arg));
#else
int rc = ::ioctl(_sockfd, request, arg);
#endif
if (rc != 0) error();
}
void SocketImpl::setSockfd(poco_socket_t aSocket)
{
poco_assert(sockfd() == POCO_INVALID_SOCKET);
_sockfd = aSocket;
}
void SocketImpl::error()
{
std::string empty;
error(lastError(), empty);
}
void SocketImpl::error(const std::string& arg)
{
error(lastError(), arg);
}
void SocketImpl::error(int code)
{
std::string arg;
error(code, arg);
}
void SocketImpl::error(int code, const std::string& arg)
{
switch (code)
{
case POCO_ESYSNOTREADY:
throw NetException("Net subsystem not ready");
case POCO_ENOTINIT:
throw NetException("Net subsystem not initialized");
case POCO_EINTR:
throw IOException("Interrupted");
case POCO_EACCES:
throw IOException("Permission denied");
case POCO_EFAULT:
throw IOException("Bad address");
case POCO_EINVAL:
throw InvalidArgumentException();
case POCO_EMFILE:
throw IOException("Too many open files");
case POCO_EWOULDBLOCK:
throw IOException("Operation would block");
case POCO_EINPROGRESS:
throw IOException("Operation now in progress");
case POCO_EALREADY:
throw IOException("Operation already in progress");
case POCO_ENOTSOCK:
throw IOException("Socket operation attempted on non-socket");
case POCO_EDESTADDRREQ:
throw NetException("Destination address required");
case POCO_EMSGSIZE:
throw NetException("Message too long");
case POCO_EPROTOTYPE:
throw NetException("Wrong protocol type");
case POCO_ENOPROTOOPT:
throw NetException("Protocol not available");
case POCO_EPROTONOSUPPORT:
throw NetException("Protocol not supported");
case POCO_ESOCKTNOSUPPORT:
throw NetException("Socket type not supported");
case POCO_ENOTSUP:
throw NetException("Operation not supported");
case POCO_EPFNOSUPPORT:
throw NetException("Protocol family not supported");
case POCO_EAFNOSUPPORT:
throw NetException("Address family not supported");
case POCO_EADDRINUSE:
throw NetException("Address already in use", arg);
case POCO_EADDRNOTAVAIL:
throw NetException("Cannot assign requested address", arg);
case POCO_ENETDOWN:
throw NetException("Network is down");
case POCO_ENETUNREACH:
throw NetException("Network is unreachable");
case POCO_ENETRESET:
throw NetException("Network dropped connection on reset");
case POCO_ECONNABORTED:
throw ConnectionAbortedException();
case POCO_ECONNRESET:
throw ConnectionResetException();
case POCO_ENOBUFS:
throw IOException("No buffer space available");
case POCO_EISCONN:
throw NetException("Socket is already connected");
case POCO_ENOTCONN:
throw NetException("Socket is not connected");
case POCO_ESHUTDOWN:
throw NetException("Cannot send after socket shutdown");
case POCO_ETIMEDOUT:
throw TimeoutException();
case POCO_ECONNREFUSED:
throw ConnectionRefusedException(arg);
case POCO_EHOSTDOWN:
throw NetException("Host is down");
case POCO_EHOSTUNREACH:
throw NetException("No route to host");
default:
throw IOException(NumberFormatter::format(code) + arg);
}
}
} } // namespace Poco::Net
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?