TcpClient类介绍[3-1]
来源:互联网 发布:java三层架构是哪三层 编辑:程序博客网 时间:2024/06/03 21:48
说明:
调用Connector类的start() ,新建socket非阻塞连接服务器;
调用Connector类的shutdown() ,关闭套接字的写管道;
调用Connector 类的stop() ,让epoll 不再关注套接字对应Channel 上的事件,将Channel从EPOLL类的channels_中移除,且从 epoll监听集合中移除;
TcpClient::newConnection中新建Socket以及对应的Channel,再将本层的函数
connectionCallback_/messageCallback_/writeCompleteCallback_注册给该Channel ;
TcpClient.h
#ifndef MUDUO_NET_TCPCLIENT_H
#define MUDUO_NET_TCPCLIENT_H
#include <boost/noncopyable.hpp>
#include <muduo/base/Mutex.h>
#include <muduo/net/TcpConnection.h>
namespace muduo
{
namespace net
{
class Connector;
typedef boost::shared_ptr<Connector> ConnectorPtr;
class TcpClient : boost::noncopyable
{
public:
// TcpClient(EventLoop* loop);
// TcpClient(EventLoop* loop, const string& host, uint16_t port);
TcpClient(EventLoop* loop,
const InetAddress& serverAddr,
const string& name);
~TcpClient(); // force out-line dtor, for scoped_ptr members.
void connect();
void disconnect();
void stop();
TcpConnectionPtr connection() const
{
MutexLockGuard lock(mutex_);
return connection_;
}
EventLoop* getLoop() const { return loop_; }
bool retry() const;
void enableRetry() { retry_ = true; }
/// Set connection callback.
/// Not thread safe.
void setConnectionCallback(const ConnectionCallback& cb)
{ connectionCallback_ = cb; }
/// Set message callback.
/// Not thread safe.
void setMessageCallback(const MessageCallback& cb)
{ messageCallback_ = cb; }
/// Set write complete callback.
/// Not thread safe.
void setWriteCompleteCallback(const WriteCompleteCallback& cb)
{ writeCompleteCallback_ = cb; }
private:
/// Not thread safe, but in loop
void newConnection(int sockfd);
/// Not thread safe, but in loop
void removeConnection(const TcpConnectionPtr& conn);
EventLoop* loop_;
ConnectorPtr connector_; // avoid revealing Connector
const string name_;
ConnectionCallback connectionCallback_;
MessageCallback messageCallback_;
WriteCompleteCallback writeCompleteCallback_;
bool retry_; // atmoic
bool connect_; // atomic
// always in loop thread
int nextConnId_;
mutable MutexLock mutex_;
TcpConnectionPtr connection_; // @BuardedBy mutex_
};
}
}
#endif // MUDUO_NET_TCPCLIENT_H
TcpClient.cc
#include <muduo/net/TcpClient.h>
#include <muduo/base/Logging.h>
#include <muduo/net/Connector.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/SocketsOps.h>
#include <boost/bind.hpp>
#include <stdio.h> // snprintf
using namespace muduo;
using namespace muduo::net;
// TcpClient::TcpClient(EventLoop* loop)
// : loop_(loop)
// {
// }
// TcpClient::TcpClient(EventLoop* loop, const string& host, uint16_t port)
// : loop_(CHECK_NOTNULL(loop)),
// serverAddr_(host, port)
// {
// }
namespace muduo
{
namespace net
{
namespace detail
{
void removeConnection(EventLoop* loop, const TcpConnectionPtr& conn)
{
loop->queueInLoop(boost::bind(&TcpConnection::connectDestroyed, conn));
}
void removeConnector(const ConnectorPtr& connector)
{
//connector->
}
}
}
}
/*
初始化要连接的服务器的addr
*/
TcpClient::TcpClient(EventLoop* loop,
const InetAddress& serverAddr,
const string& name)
: loop_(CHECK_NOTNULL(loop)),
connector_(new Connector(loop, serverAddr)),
name_(name),
connectionCallback_(defaultConnectionCallback),
messageCallback_(defaultMessageCallback),
retry_(false),
connect_(true),
nextConnId_(1)
{
connector_->setNewConnectionCallback(
boost::bind(&TcpClient::newConnection, this, _1));
// FIXME setConnectFailedCallback
LOG_INFO << "TcpClient::TcpClient[" << name_
<< "] - connector " << get_pointer(connector_);
}
TcpClient::~TcpClient()
{
LOG_INFO << "TcpClient::~TcpClient[" << name_
<< "] - connector " << get_pointer(connector_);
TcpConnectionPtr conn;
{
MutexLockGuard lock(mutex_);
conn = connection_;
}
if (conn)
{
// FIXME: not 100% safe, if we are in different thread
CloseCallback cb = boost::bind(&detail::removeConnection, loop_, _1);
loop_->runInLoop(
boost::bind(&TcpConnection::setCloseCallback, conn, cb));
}
else
{
connector_->stop();
// FIXME: HACK
loop_->runAfter(1, boost::bind(&detail::removeConnector, connector_));
}
}
/*
调用Connector 类的start() ,新建socket 非阻塞连接服务器
*/
void TcpClient::connect()
{
// FIXME: check state
LOG_INFO << "TcpClient::connect[" << name_ << "] - connecting to "
<< connector_->serverAddress().toIpPort();
connect_ = true;
connector_->start();
}
/*
调用Connector 类的shutdown() ,关闭套接字的写管道
*/
void TcpClient::disconnect()
{
connect_ = false;
{
MutexLockGuard lock(mutex_);
if (connection_)
{
connection_->shutdown();
}
}
}
/*
调用Connector 类的stop() ,
让epoll 不再关注套接字对应Channel 上的事件;
将Channel 从EPOLL类的channels_ 中移除,且从epoll监听集合中移除;
*/
void TcpClient::stop()
{
connect_ = false;
connector_->stop();
}
/*
new TcpConnection 即新建Socket以及对应的Channel,
再将本层的函数connectionCallback_/messageCallback_/writeCompleteCallback_
注册给该Channel ;
*/
void TcpClient::newConnection(int sockfd)
{
loop_->assertInLoopThread();
InetAddress peerAddr(sockets::getPeerAddr(sockfd));
char buf[32];
snprintf(buf, sizeof buf, ":%s#%d", peerAddr.toIpPort().c_str(), nextConnId_);
++nextConnId_;
string connName = name_ + buf;
InetAddress localAddr(sockets::getLocalAddr(sockfd));
// FIXME poll with zero timeout to double confirm the new connection
// FIXME use make_shared if necessary
TcpConnectionPtr conn(new TcpConnection(loop_,
connName,
sockfd,
localAddr,
peerAddr));
conn->setConnectionCallback(connectionCallback_);
conn->setMessageCallback(messageCallback_);
conn->setWriteCompleteCallback(writeCompleteCallback_);
conn->setCloseCallback(
boost::bind(&TcpClient::removeConnection, this, _1)); // FIXME: unsafe
{
MutexLockGuard lock(mutex_);
connection_ = conn;
}
conn->connectEstablished();
}
/*
TcpConnection::connectDestroyed里面即会调用
TcpClient::connectionCallback_函数
*/
void TcpClient::removeConnection(const TcpConnectionPtr& conn)
{
loop_->assertInLoopThread();
assert(loop_ == conn->getLoop());
{
MutexLockGuard lock(mutex_);
assert(connection_ == conn);
connection_.reset();
}
loop_->queueInLoop(boost::bind(&TcpConnection::connectDestroyed, conn));
if (retry_ && connect_)
{
LOG_INFO << "TcpClient::connect[" << name_ << "] - Reconnecting to "
<< connector_->serverAddress().toIpPort();
connector_->restart();
}
}
- TcpClient类介绍[3-1]
- TcpClient 类
- tcpclient类
- TCPClient
- TcpClient tcpClient
- TcpClient类和TcpListener类
- TcpClient类和TcpListener类
- TcpClient类异步接收数据
- TcpListener类与TcpClient类的使用
- Socket编程3-TcpListener,TcpClient-UdpClient
- 在C#中带连接超时功能的TcpClient类
- tcpclient.c
- tcpclient tcpserver
- c# tcpclient
- TcpListener & TcpClient
- winform网络编程之TcpClient类,TcpListener类和UdpClient类
- SOCKET Communication writen in C# (3) TcpListener 和TcpClient 异步非阻塞
- C#网络编程之TcpListener与TcpClient类常用方法与属性(7)
- Winform多线程
- windows下telnet命令查看memcache服务器数据
- java.sql.SQLException: 无法从套接字读取更多的数据出现的原因
- 时间都去哪儿了?开源一个统计iPhone上App运行时间和打开次数的小工具 如今,大家每天都有大量时间花在手机上,但是,大家有没有想过自己的时间都花在哪些App上了呢?相信很多人都有
- C语言谜题--经典
- TcpClient类介绍[3-1]
- 【转】jvm 内存模型
- CPU cache 内存
- 如何允许 WinXP 和 Win7 自动创建 dump 文件
- 1001-content-Assets
- JavaScript(12)浏览器对象模型
- linux查看端口与关闭端口
- Japan - POJ 3067 排序+树状数组
- 有道搜索框(tyvj 1228)