与服务端通信异步接口的定义方案

1.一般做法是客户端sendMessage,在另外一个线程里不断recv返回的消息,然后通过onMessage虚函数处理返回的消息。

2.这种做法是sendMessage的时候给它设置一个处理应答消息的回调,将所有回调管理起来,当服务端返回应答消息的时候,找到对应的回调执行。

以下做法考虑到LoginViewer是一个界面当应答消息没有返回的时候我们就关闭掉这个界面,此时这个类就销毁了,之后再调用回调会crash掉。

所以这里用的是一个智能指针,虽然解决了上述崩溃的问题,但是又带来一个新的问题,如果应答消息没有返回此时这个对象就销毁不了。可以用一个timer检测应答消息是否超时,如果超时就删除。

// test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include "Logger.h"
#include <memory>
#include <string>
#include <map>
#include <functional>

struct Message {
	Message(int id, const std::string &content) 
		: id(id), content(content) { }
	int id;
	std::string content;
};

typedef std::shared_ptr<Message> MessagePtr;
typedef std::function<void(const MessagePtr &resPtr)> ResCallback;

class DBus
{
public:
	static DBus* Instance()
	{
		static DBus *instance = NULL;
		if (NULL == instance) {
			instance = new DBus();
		}
		return instance;
	}

	void login(const MessagePtr &request, const ResCallback &resFunc)
	{
		callbacks_[request->id] = resFunc;
		std::cout << "login start" << std::endl;
	}

	void onMessage(const MessagePtr &resPtr)
	{
		ResCallback func = callbacks_[resPtr->id];
		callbacks_.erase(resPtr->id);
		func(resPtr);
	}

private:
	std::map<int, ResCallback> callbacks_;
};

class LoginViewer : public std::enable_shared_from_this<LoginViewer>
{
public:
	LoginViewer()
	{
		test_ = "testtest...";
		std::cout << "LoginViewer" << std::endl;
	}

	~LoginViewer()
	{
		std::cout << "~LoginViewer" << std::endl;
	}

	void login()
	{
		MessagePtr request(new Message(123, "hello, world!"));
		DBus::Instance()->login(request, std::bind(&LoginViewer::loginResult, shared_from_this(), std::placeholders::_1));
	}

private:
	void loginResult(const MessagePtr &resPtr)
	{
		std::cout << test_ << std::endl;
		std::cout << "login result, message id:" << resPtr->id << ", content:" << resPtr->content << std::endl;
	}

private:
	std::string test_;
};

int _tmain(int argc, _TCHAR* argv[])
{
	{	
		std::shared_ptr<LoginViewer> loginViewer(new LoginViewer());
		loginViewer->login();
	}

	MessagePtr response(new Message(123, "success"));
	DBus::Instance()->onMessage(response);

	system("pause");
	return 0;
}



你可能感兴趣的:(与服务端通信异步接口的定义方案)