📄 socketimpl.cpp
字号:
//// SocketImpl.cpp//// $Id: //poco/1.2/Net/src/SocketImpl.cpp#2 $//// Library: Net// Package: Sockets// Module: SocketImpl//// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.// and Contributors.//// Permission is hereby granted, free of charge, to any person or organization// obtaining a copy of the software and accompanying documentation covered by// this license (the "Software") to use, reproduce, display, distribute,// execute, and transmit the Software, and to prepare derivative works of the// Software, and to permit third-parties to whom the Software is furnished to// do so, all subject to the following:// // The copyright notices in the Software and this entire statement, including// the above license grant, this restriction and the following disclaimer,// must be included in all copies of the Software, in whole or in part, and// all derivative works of the Software, unless such copies or derivative// works are solely in the form of machine-executable object code generated by// a source language processor.// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER// DEALINGS IN THE SOFTWARE.//#include "Poco/Net/SocketImpl.h"#include "Poco/Net/NetException.h"#include "Poco/Net/StreamSocketImpl.h"#include "Poco/NumberFormatter.h"#include "Poco/Timestamp.h"#include <string.h>using Poco::IOException;using Poco::TimeoutException;using Poco::InvalidArgumentException;using Poco::NumberFormatter;using Poco::Timespan;namespace Poco {namespace Net {SocketImpl::SocketImpl(): _sockfd(POCO_INVALID_SOCKET){}SocketImpl::SocketImpl(poco_socket_t sockfd): _sockfd(sockfd){}SocketImpl::~SocketImpl(){ close();} SocketImpl* SocketImpl::acceptConnection(SocketAddress& clientAddr){ 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); poco_socket_t sd; do { sd = ::accept(_sockfd, pSA, &saLen); } while (sd == POCO_INVALID_SOCKET && lastError() == POCO_EINTR); if (sd != POCO_INVALID_SOCKET) { clientAddr = SocketAddress(pSA, saLen); return new StreamSocketImpl(sd); } error(); // will throw return 0;}void SocketImpl::connect(const SocketAddress& address){ if (_sockfd == POCO_INVALID_SOCKET) { init(address.af()); } int rc; do { rc = ::connect(_sockfd, address.addr(), address.length()); } while (rc != 0 && lastError() == POCO_EINTR); if (rc != 0) error(address.toString());}void SocketImpl::connect(const SocketAddress& address, const Poco::Timespan& timeout){ poco_assert (_sockfd == POCO_INVALID_SOCKET); init(address.af()); setBlocking(false); try { int rc = ::connect(_sockfd, address.addr(), address.length()); if (rc != 0) { if (lastError() != POCO_EINPROGRESS && lastError() != POCO_EWOULDBLOCK) error(address.toString()); if (!poll(timeout, SELECT_READ | SELECT_WRITE)) throw Poco::TimeoutException("connect timed out", address.toString()); int err = socketError(); if (err != 0) error(err); } } catch (Poco::Exception&) { setBlocking(true); throw; } setBlocking(true);}void SocketImpl::connectNB(const SocketAddress& address){ if (_sockfd == POCO_INVALID_SOCKET) { init(address.af()); } setBlocking(false); int rc = ::connect(_sockfd, address.addr(), address.length()); if (rc != 0) { if (lastError() != POCO_EINPROGRESS && lastError() != POCO_EWOULDBLOCK) error(address.toString()); }}void SocketImpl::bind(const SocketAddress& address, bool reuseAddress){ if (_sockfd == POCO_INVALID_SOCKET) { init(address.af()); } if (reuseAddress) { setReuseAddress(true); setReusePort(true); } int rc = ::bind(_sockfd, address.addr(), address.length()); if (rc != 0) error(address.toString());} void SocketImpl::listen(int backlog){ poco_assert (_sockfd != POCO_INVALID_SOCKET); int rc = ::listen(_sockfd, backlog); if (rc != 0) error();}void SocketImpl::close(){ if (_sockfd != POCO_INVALID_SOCKET) { poco_closesocket(_sockfd); _sockfd = POCO_INVALID_SOCKET; }}void SocketImpl::shutdownReceive(){ poco_assert (_sockfd != POCO_INVALID_SOCKET); int rc = ::shutdown(_sockfd, 0); if (rc != 0) error();} void SocketImpl::shutdownSend(){ poco_assert (_sockfd != POCO_INVALID_SOCKET); int rc = ::shutdown(_sockfd, 1); if (rc != 0) error();} void SocketImpl::shutdown(){ poco_assert (_sockfd != POCO_INVALID_SOCKET); int rc = ::shutdown(_sockfd, 2); if (rc != 0) error();}int SocketImpl::sendBytes(const void* buffer, int length, int flags){ poco_assert (_sockfd != POCO_INVALID_SOCKET); int rc; do { rc = ::send(_sockfd, reinterpret_cast<const char*>(buffer), length, flags); } while (rc < 0 && lastError() == POCO_EINTR); if (rc < 0) error(); return rc;}int SocketImpl::receiveBytes(void* buffer, int length, int flags){ poco_assert (_sockfd != POCO_INVALID_SOCKET);#if defined(POCO_BROKEN_TIMEOUTS) if (_recvTimeout.totalMicroseconds() != 0) { if (!poll(_recvTimeout, SELECT_READ)) throw TimeoutException(); }#endif int rc; do { rc = ::recv(_sockfd, reinterpret_cast<char*>(buffer), length, flags); } while (rc < 0 && lastError() == POCO_EINTR); if (rc < 0) { if (lastError() == POCO_EAGAIN || lastError() == POCO_ETIMEDOUT) throw TimeoutException(); else error(); } return rc;}int SocketImpl::sendTo(const void* buffer, int length, const SocketAddress& address, int flags){ poco_assert (_sockfd != POCO_INVALID_SOCKET); int rc; do { rc = ::sendto(_sockfd, reinterpret_cast<const char*>(buffer), length, flags, address.addr(), address.length()); } while (rc < 0 && lastError() == POCO_EINTR); if (rc < 0) error(); return rc;}int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags){ poco_assert (_sockfd != POCO_INVALID_SOCKET);#if defined(POCO_BROKEN_TIMEOUTS) if (_recvTimeout.totalMicroseconds() != 0) { if (!poll(_recvTimeout, SELECT_READ)) throw TimeoutException(); }#endif char abuffer[SocketAddress::MAX_ADDRESS_LENGTH]; struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(abuffer); poco_socklen_t saLen = sizeof(abuffer); int rc; do { rc = ::recvfrom(_sockfd, reinterpret_cast<char*>(buffer), length, flags, pSA, &saLen); } while (rc < 0 && lastError() == POCO_EINTR); if (rc >= 0) { address = SocketAddress(pSA, saLen); } else { if (lastError() == POCO_EAGAIN || lastError() == POCO_ETIMEDOUT) throw TimeoutException(); else error(); } return rc;}void SocketImpl::sendUrgent(unsigned char data){ int rc = ::send(_sockfd, reinterpret_cast<const char*>(&data), sizeof(data), MSG_OOB); if (rc < 0) error();}int SocketImpl::available(){ int result; ioctl(FIONREAD, result); return result;}bool SocketImpl::poll(const Poco::Timespan& timeout, int mode){ fd_set fdRead; fd_set fdWrite; fd_set fdExcept; FD_ZERO(&fdRead); FD_ZERO(&fdWrite); FD_ZERO(&fdExcept); if (mode & SELECT_READ) { FD_SET(_sockfd, &fdRead); } if (mode & SELECT_WRITE) { FD_SET(_sockfd, &fdWrite); } if (mode & SELECT_ERROR) { FD_SET(_sockfd, &fdExcept); } Poco::Timespan remainingTime(timeout); int rc; do { struct timeval tv; tv.tv_sec = (long) remainingTime.totalSeconds(); tv.tv_usec = (long) remainingTime.useconds(); Poco::Timestamp start; rc = ::select(int(_sockfd) + 1, &fdRead, &fdWrite, &fdExcept, &tv); if (rc < 0 && lastError() == POCO_EINTR) { Poco::Timestamp end; Poco::Timespan waited = end - start; if (waited > remainingTime) remainingTime -= waited; else remainingTime = 0; } } while (rc < 0 && lastError() == POCO_EINTR); if (rc < 0) error(); return rc > 0; } void SocketImpl::setSendBufferSize(int size){ setOption(SOL_SOCKET, SO_SNDBUF, size);} int SocketImpl::getSendBufferSize(){ int result; getOption(SOL_SOCKET, SO_SNDBUF, result); return result;}void SocketImpl::setReceiveBufferSize(int size){ setOption(SOL_SOCKET, SO_RCVBUF, size);} int SocketImpl::getReceiveBufferSize(){ int result; getOption(SOL_SOCKET, SO_RCVBUF, result); return result;}void SocketImpl::setSendTimeout(const Poco::Timespan& timeout){#if defined(_WIN32) int value = (int) timeout.totalMilliseconds(); setOption(SOL_SOCKET, SO_SNDTIMEO, value);#else setOption(SOL_SOCKET, SO_SNDTIMEO, timeout);#endif}Poco::Timespan SocketImpl::getSendTimeout(){ Timespan result;#if defined(_WIN32) int value; getOption(SOL_SOCKET, SO_SNDTIMEO, value); result = Timespan::TimeDiff(value)*1000;#else getOption(SOL_SOCKET, SO_SNDTIMEO, result);#endif return result;}void SocketImpl::setReceiveTimeout(const Poco::Timespan& timeout){#if defined(_WIN32) int value = (int) timeout.totalMilliseconds(); setOption(SOL_SOCKET, SO_RCVTIMEO, value);#else setOption(SOL_SOCKET, SO_RCVTIMEO, timeout);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -