1.概述
“This class provides an interface to a TCP stream socket.”,StreamSocket类是Socket类的子类,用作TCP客户端。本篇系统环境为linux,欢迎交流和指出问题,转载请标明作者和链接地址http://blog.csdn.net/lz_obj/article/details/75825413。
2.类图
关系说明:
StreamSocket类公有继承于Socket类。Socket类拥有私有成员(SocketImpl*)_pImpl。SocketImpl类是StreamSocketImpl类的父类,Socket类的构造函数将new子类StreamSocketImpl的堆地址赋值给Socket的私有数据成员_pImpl,Socket类在接口实现上调用了SocketImpl类和StreamSocketImpl类的方法。总之,StreamSocket类接口对于linux系统调用的运用,本质实现于Socket、SocketImpl、StreamSocketImpl等类。
3.接口解析
3.1构造函数
StreamSocket::StreamSocket(): Socket(new StreamSocketImpl)
{
}
StreamSocket构造函数调用父类Socket的构造函数Socket(SocketImpl* pImpl);
Socket::Socket(SocketImpl* pImpl): _pImpl(pImpl)
{
poco_check_ptr(_pImpl);
}
(SocketImpl*)_pImpl是Socket类的私有成员,SocketImpl类是StreamSocketImpl类的父类,这里用到了“工厂模式”。
SocketImpl::SocketImpl():_sockfd(POCO_INVALID_SOCKET),_blocking(true)
{
}
StreamSocketImpl::StreamSocketImpl()
{
}
父类SocketImpl构造函数对成员_sockfd和_blocking进行初始化,子类StreamSocketImpl构造函数未进行操作。SocketImpl类私有成员_sockfd、_blocking声明如下:poco_socket_t _sockfd;bool _blocking。”poco_socket_t”是int数据类型的宏,_sockfd代表socket描述符,_blocking代表是否阻塞。前者被初始化为POCO_INVALID_SOCKET非法socketfd,后者被初始化为true阻塞态。
3.2析构函数
StreamSocket::~StreamSocket()
{
}
Socket::~Socket()
{
_pImpl->release();
}
SocketImpl类是RefCountedObject类的子类,release()是RefCountedObject类的方法。
inline void RefCountedObject::release() const throw()
{
try
{
if (--_counter == 0) delete this;
}
catch (...)
{
poco_unexpected();
}
}
“delete this”用于释放StreamSocket类运行构造函数时,SocketImpl* pImpl = new StreamSocketImpl操作所动态分配的空间。
3.3connect连接函数
void StreamSocket::connect(const SocketAddress& address)
{
impl()->connect(address);
}
void SocketImpl::connect(const SocketAddress& address)
{
if (_sockfd == POCO_INVALID_SOCKET)
{
init(address.af());
}
int rc;
do
{
#if defined(POCO_VXWORKS)
rc = ::connect(_sockfd, (sockaddr*) address.addr(), address.length());
#else
rc = ::connect(_sockfd, address.addr(), address.length());
#endif
}
while (rc != 0 && lastError() == POCO_EINTR);
if (rc != 0)
{
int err = lastError();
error(err, address.toString());
}
}
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();
#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
setOption(SOL_SOCKET, SO_NOSIGPIPE, 1);
#endif
}
connect完成系统调用和操作:
1)判断socket描述符是否是