muduo

muduo 是一个用 C++ 编写的高性能网络库,由陈硕开发,具有事件驱动、非阻塞 I/O 等特点,常用于构建高性能的网络服务器和客户端程序。结合你之前给出的错误信息,它与 muduo 库中的 EventLoop 类密切相关,下面为你详细介绍 muduo 库以及针对该错误的相关分析和解决办法。

这个库很好的封装了Tcpsocket模块的代码,让人在上层用得也非常优雅,采用事件驱动模型,借助 epoll 或 kqueue 等 I/O 多路复用技术,能够高效处理大量并发连。

TcpServer模块

TcpServer 类的主要功能包括:

  • 监听端口:绑定指定的 IP 地址和端口号,开始监听客户端的连接请求。
  • 管理连接:负责接受客户端的连接,创建和管理 TcpConnection 对象,处理连接的建立、断开等事件。
  • 事件处理:提供回调函数接口,允许开发者处理连接建立、消息接收、连接关闭等事件。
class InetAddress : public muduo::copyable
{
public:
	InetAddress(StringArg ip, uint16_t port, bool ipv6 = false);
};

class TcpServer : noncopyable
{
public:
	enum Option
	{
		kNoReusePort,
		kReusePort,
	};
	TcpServer(EventLoop* loop,
		const InetAddress& listenAddr,
		const string& nameArg,
		Option option = kNoReusePort);
	void setThreadNum(int numThreads);
	void start();
	/// 
	当⼀个新连接建⽴成功的时候被调⽤

		void setConnectionCallback(const ConnectionCallback& cb)
	{
		connectionCallback_ = cb;
	}
	/// 
	消息的业务处理回调函数--
		这是收到新连接消息的时候被调⽤的函数

		void setMessageCallback(const MessageCallback & cb)
	{
		messageCallback_ = cb;
	}
};

EvenLoop

EventLoop 主要负责

  1. 事件循环:不断地循环检查并处理各种 I/O 事件(如可读、可写事件)和定时事件。
  2. 事件分发:将发生的事件分发给对应的处理函数进行处理。
  3. 线程绑定EventLoop 是线程绑定的,即一个 EventLoop 实例只能在创建它的线程中运行,保证了线程安全性和事件处理的顺序性。
class EventLoop : noncopyable
{
public:
	/// Loops forever.
	/// Must be called in the same thread as creation of the object.
	void loop();
	/// Quits loop.
	/// This is not 100% thread safe, if you call through a raw pointer,
	/// better to call through shared_ptr<EventLoop> for 100% safety.
	void quit();
	TimerId runAt(Timestamp time, TimerCallback cb);
	/// Runs callback after @c delay seconds.
	/// Safe to call from other threads.
	TimerId runAfter(double delay, TimerCallback cb);
	/// Runs callback every @c interval seconds.
	/// Safe to call from other threads.
	TimerId runEvery(double interval, TimerCallback cb);
	/// Cancels the timer.
	/// Safe to call from other threads.
	void cancel(TimerId timerId);
private:
	std::atomic<bool> quit_;
	std::unique_ptr<Poller> poller_;
	mutable MutexLock mutex_;
	std::vector<Functor> pendingFunctors_ GUARDED_BY(mutex_);
};

Tcpconnection

TcpConnection 主要负责:

  • 连接管理:处理 TCP 连接的建立、断开和状态维护。
  • 数据读写:提供数据的读取和发送功能,支持非阻塞 I/O 操作。
  • 事件处理:处理连接上的各种事件,如连接建立、连接关闭、数据可读、数据可写等,并通过回调函数通知用户。

class TcpConnection : noncopyable,
	public std::enable_shared_from_this<TcpConnection>
{
public:
	/// Constructs a TcpConnection with a connected sockfd
	///
	/// User should not create this object.
	TcpConnection(EventLoop* loop,
		const string& name,
		int sockfd,
		const InetAddress& localAddr,
		const InetAddress& peerAddr);
	bool connected() const { return state_ == kConnected; }
	bool disconnected() const { return state_ == kDisconnected; }
	void send(string&& message); // C++11
	void send(const void* message, int len);
	void send(const StringPiece& message);
	// void send(Buffer&& message); // C++11
	void send(Buffer* message);  // this one will swap data
	void shutdown(); // NOT thread safe, no simultaneous calling
	void setContext(const boost::any& context)
	{
		context_ = context;
	}
	const boost::any& getContext() const
	{
		return context_;
	}
	boost::any* getMutableContext()
	{
		return &context_;
	}
	void setConnectionCallback(const ConnectionCallback& cb)
	{
		connectionCallback_ = cb;
	}
	void setMessageCallback(const MessageCallback& cb)
	{
		messageCallback_ = cb;
	}
private:
	enum StateE { kDisconnected, kConnecting, kConnected, kDisconnecting };
	EventLoop* loop_;
	ConnectionCallback connectionCallback_;
	MessageCallback messageCallback_;
	WriteCompleteCallback writeCompleteCallback_;
	boost::any context_;
};

TcpClient

相比较于TcpServer,TcpClient主要负责的就是客户端的连接操作


class TcpClient : noncopyable
{
public:
	// TcpClient(EventLoop* loop);
	// TcpClient(EventLoop* loop, const string& host, uint16_t port);
	TcpClient(EventLoop* loop,
		const InetAddress& serverAddr,
		const string& nameArg);
	~TcpClient();  // force out-line dtor, for std::unique_ptr members.
	void connect();//
	连接服务器

		void disconnect();//
	关闭连接

		void stop();
	//
	获取客⼾端对应的通信连接
		Connection
		对象的接⼝,发起
		connect
		后,有可能还没有连接建⽴成
		功
		TcpConnectionPtr connection() const
	{
		MutexLockGuard lock(mutex_);
		return connection_;
	}
	/// 
	连接服务器成功时的回调函数

		void setConnectionCallback(ConnectionCallback cb)
	{
		connectionCallback_ = std::move(cb);
	}
	/// 
	收到服务器发送的消息时的回调函数

		void setMessageCallback(MessageCallback cb)
	{
		messageCallback_ = std::move(cb);
	}
private:
	EventLoop* loop_;
	ConnectionCallback connectionCallback_;
	MessageCallback messageCallback_;
	WriteCompleteCallback writeCompleteCallback_;
	TcpConnectionPtr connection_ GUARDED_BY(mutex_);
};


class CountDownLatch : noncopyable
{
public:
	explicit CountDownLatch(int count);
	void wait() {
		MutexLockGuard lock(mutex_);
		while (count_ > 0)
		{
			condition_.wait();
		}
	}
	void countDown() {
		MutexLockGuard lock(mutex_); --count_;
		if (count_ == 0)
		{
			condition_.notifyAll();
		}
	}
	int getCount() const;
private:
	mutable MutexLock mutex_;
	Condition condition_ GUARDED_BY(mutex_);
	int count_ GUARDED_BY(mutex_);
};

Buffer

 在Buffer中最常用的方法就是string retrieveAllAsString(),这个方法就是取出当前IO就绪中的数据。


class Buffer : public muduo::copyable
{
public:
	static const size_t kCheapPrepend = 8;
	static const size_t kInitialSize = 1024;
	explicit Buffer(size_t initialSize = kInitialSize)
		: buffer_(kCheapPrepend + initialSize),
		readerIndex_(kCheapPrepend),
		writerIndex_(kCheapPrepend);
	void swap(Buffer& rhs)
		size_t readableBytes() const
		size_t writableBytes() const
		const char* peek() const
		const char* findEOL() const
		const char* findEOL(const char* start) const
		void retrieve(size_t len)
		void retrieveInt64()
		void retrieveInt32()
		void retrieveInt16() void retrieveInt8()
		string retrieveAllAsString()
		string retrieveAsString(size_t len)
		void append(const StringPiece& str)
		void append(const char* /*restrict*/ data, size_t len)
		void append(const void* /*restrict*/ data, size_t len)
		char* beginWrite()
		const char* beginWrite() const
		void hasWritten(size_t len)
		void appendInt64(int64_t x)
		void appendInt32(int32_t x)
		void appendInt16(int16_t x)
		void appendInt8(int8_t x)
		int64_t readInt64()
		int32_t readInt32()
		int16_t readInt16()
		int8_t readInt8()
		int64_t peekInt64() const
		int32_t peekInt32() const
		int16_t peekInt16() const
		int8_t peekInt8() const
		void prependInt64(int64_t x)
		void prependInt32(int32_t x)
		void prependInt16(int16_t x)
		void prependInt8(int8_t x)
		void prepend(const void* /*restrict*/ data, size_t len)
private:
	std::vector<char> buffer_;
	size_t readerIndex_;
	size_t writerIndex_;
	static const char kCRLF[];
};

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐