Registration mechanism using message Message Communication Mechanism

A demand:

The abstract message communication, support udp, tcp, zmq etc.

Two achieved:

1. The message communication entity

#ifndef SRC_MESSAGE_COMMUNICATE_ENTITY_HPP_
#define SRC_MESSAGE_COMMUNICATE_ENTITY_HPP_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <algorithm>
using namespace std;
class message_communicate_entity {
public:
	message_communicate_entity() = default;
	virtual ~message_communicate_entity() = default;
public:
	virtual bool init() = 0;
	virtual int send(const char *buf, int len) = 0;
	virtual int recv(char *recv_buf, int buf_len) = 0;
};

#endif /* SRC_MESSAGE_COMMUNICATE_ENTITY_HPP_ */

2. The message communication manufacturer

#ifndef SRC_MESSAGE_COMMUNICATE_ENTITY_MAKER_HPP_
#define SRC_MESSAGE_COMMUNICATE_ENTITY_MAKER_HPP_
#include "message_communicate_entity.hpp"
#include <string>
#include <unordered_map>
#include <functional>
#include <memory>
class message_communicate_entity_maker {
public:
	static message_communicate_entity *make(const string &entity_type) {
		auto it = map_.find(entity_type);
		if (end(map_) == it) {
			return nullptr;
		}
		return it->second();
	}
	static unique_ptr<message_communicate_entity>make_unique_ptr(const string &entity_type) {
		return unique_ptr<message_communicate_entity>(make(entity_type));
	}
	static std::shared_ptr<message_communicate_entity>make_shared_ptr(const string &entity_type) {
		return std::shared_ptr<message_communicate_entity>(make(entity_type));
	}
public:
	template<class T>
	struct register_t {
		register_t(const string &key){
			message_communicate_entity_maker::get().map_.emplace(key, [] {return new T();});
		}
		template<typename... Args>
		register_t(const string &key, Args... args){
			message_communicate_entity_maker::get().map_.emplace(key, [=] {return new T(args...);});
		}
	};
private:
	message_communicate_entity_maker() = default;
	message_communicate_entity_maker(const message_communicate_entity_maker &) = delete;
	message_communicate_entity_maker operator = (const message_communicate_entity_maker &) = delete;
	message_communicate_entity_maker(message_communicate_entity_maker &&) = delete;
	~message_communicate_entity_maker() = default;
private:
	inline static message_communicate_entity_maker &get() {
		static message_communicate_entity_maker maker;
		return maker;
	}
private:
	static unordered_map<string, function<message_communicate_entity *()>>map_;	// key -- entity type such udp_unicast
};
unordered_map<string, function<message_communicate_entity *()>>message_communicate_entity_maker::map_;
#define REGISTER_MESSAGE_COMMUNICATE_ENTITY_VNAME(T) reg_entity_##T##_
#define REGISTER_MESSAGE_COMMUNICATE_ENTITY(T, key, ...) static message_communicate_entity_maker::register_t<T> REGISTER_MESSAGE_COMMUNICATE_ENTITY_VNAME(T)(key, ##__VA_ARGS__);

#endif /* SRC_MESSAGE_COMMUNICATE_ENTITY_MAKER_HPP_ */

3.udp broadcasting services

#ifndef SRC_UDP_BROADCAST_SERVER_HPP_
#define SRC_UDP_BROADCAST_SERVER_HPP_
#include "message_communicate_entity_maker.hpp"
class udp_broadcast_server : public message_communicate_entity {
public:
	udp_broadcast_server() {
		sock_fd_ = -1;
		port_ = 17789;
		memset(&client_addr_, 0, sizeof(client_addr_));
	}
	~udp_broadcast_server() {
		if (sock_fd_ >= 0) {
			close(sock_fd_);
		}
	}
public:
	inline bool init() override {
		return init_sock_fd() && bind_sock_fd();
	}
	inline bool init_sock_fd() {
		sock_fd_ = socket(AF_INET, SOCK_DGRAM, 0);
		if (sock_fd_ < 0) {
			return false;
		}
		int so_broadcast = 1;
		return setsockopt(sock_fd_, SOL_SOCKET, SO_BROADCAST, (char *)&so_broadcast, sizeof(so_broadcast)) >= 0;
	}
	inline bool bind_sock_fd() {
		struct sockaddr_in addr = {0};
		addr.sin_family = AF_INET;
		addr.sin_addr.s_addr = htonl(INADDR_ANY);
		addr.sin_port = htons(port_);
		return bind(sock_fd_, (struct sockaddr *)&addr, sizeof(addr)) >= 0;
	}
	inline void set_port(int port) {
		port_ = port;
	}
	virtual int send(const char *buf, int len) override {
		return sendto(sock_fd_, buf, len, 0, (struct sockaddr *)&client_addr_, sizeof(client_addr_));
	}
	virtual int recv(char *recv_buf, int buf_len) override {
		if (buf_len <= 0 || buf_len > BUFSIZ) {
			return -1;
		}
		char buf[BUFSIZ] = "";
		socklen_t size = sizeof(struct sockaddr);
		int len = recvfrom(sock_fd_, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr_, &size);
		if (len <= BUFSIZ && len > 0) {
			len = min(len, buf_len);
			memcpy(recv_buf, buf, len);
		}
		return len;
	}
private:
	int sock_fd_;
	int port_;
	struct sockaddr_in client_addr_;
};
REGISTER_MESSAGE_COMMUNICATE_ENTITY(udp_broadcast_server, "udp.broadcast.server");

#endif /* SRC_UDP_BROADCAST_SERVER_HPP_ */

4.udp broadcast client

#ifndef SRC_UDP_BROADCAST_CLIENT_HPP_
#define SRC_UDP_BROADCAST_CLIENT_HPP_
#include "message_communicate_entity_maker.hpp"
class udp_broadcast_client : public message_communicate_entity {
public:
	udp_broadcast_client() {
		sock_fd_ = -1;
		port_ = 17789;
		broadcast_address_ = "255.255.255.255";
		memset(&client_addr_, 0, sizeof(client_addr_));
	}
	~udp_broadcast_client() {
		if (sock_fd_ >= 0) {
			close(sock_fd_);
		}
	}
public:
	inline bool init() override {
		return init_sock_fd();
	}
	inline bool init_sock_fd() {
		sock_fd_ = socket(AF_INET, SOCK_DGRAM, 0);
		if (sock_fd_ < 0) {
			return false;
		}
		int so_broadcast = 1;
		return setsockopt(sock_fd_, SOL_SOCKET, SO_BROADCAST, (char *)&so_broadcast, sizeof(so_broadcast)) >= 0;
	}
	inline void set_port(int port) {
		port_ = port;
	}
	inline void set_broadcast_address(const char *address) {
		broadcast_address_ = address;
	}
	virtual int send(const char *buf, int len) override {
		struct sockaddr_in dest_addr = {0};
		dest_addr.sin_family = AF_INET;
		dest_addr.sin_port = htons(port_);
		dest_addr.sin_addr.s_addr = inet_addr(broadcast_address_);
		return sendto(sock_fd_, buf, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
	}
	virtual int recv(char *recv_buf, int buf_len) override {
		if (buf_len <= 0 || buf_len > BUFSIZ) {
			return -1;
		}
		char buf[BUFSIZ] = "";
		socklen_t size = sizeof(struct sockaddr);
		int len = recvfrom(sock_fd_, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr_, &size);
		if (len <= BUFSIZ && len > 0) {
			len = min(len, buf_len);
			memcpy(recv_buf, buf, len);
		}
		return len;
	}
private:
	int sock_fd_;
	int port_;
	const char *broadcast_address_;
	struct sockaddr_in client_addr_;
};
REGISTER_MESSAGE_COMMUNICATE_ENTITY(udp_broadcast_client, "udp.broadcast.client");

#endif /* SRC_UDP_BROADCAST_CLIENT_HPP_ */

5.udp Unicast server

#ifndef SRC_UDP_UNICAST_SERVER_HPP_
#define SRC_UDP_UNICAST_SERVER_HPP_
#include "message_communicate_entity_maker.hpp"
class udp_unicast_server : public message_communicate_entity {
public:
	udp_unicast_server() {
		sock_fd_ = -1;
		port_ = 27790;
		memset(&client_addr_, 0, sizeof(client_addr_));
	}
	~udp_unicast_server() {
		if (sock_fd_ >= 0) {
			close(sock_fd_);
		}
	}
public:
	inline bool init() override {
		return init_sock_fd() && bind_sock_fd();
	}
	inline bool init_sock_fd() {
		sock_fd_ = socket(AF_INET, SOCK_DGRAM, 0);
		return sock_fd_ >= 0;
	}
	inline bool bind_sock_fd() {
		struct sockaddr_in addr = {0};
		addr.sin_family = AF_INET;
		addr.sin_addr.s_addr = htonl(INADDR_ANY);
		addr.sin_port = htons(port_);
		return bind(sock_fd_, (struct sockaddr *)&addr, sizeof(addr)) >= 0;
	}
	inline void set_port(int port) {
		port_ = port;
	}
	virtual int send(const char *buf, int len) override {
		return sendto(sock_fd_, buf, len, 0, (struct sockaddr *)&client_addr_, sizeof(client_addr_));
	}
	virtual int recv(char *recv_buf, int buf_len) override {
		if (buf_len <= 0 || buf_len > BUFSIZ) {
			return -1;
		}
		char buf[BUFSIZ] = "";
		socklen_t size = sizeof(struct sockaddr);
		int len = recvfrom(sock_fd_, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr_, &size);
		if (len <= BUFSIZ && len > 0) {
			len = min(len, buf_len);
			memcpy(recv_buf, buf, len);
		}
		return len;
	}
private:
	int sock_fd_;
	int port_;
	struct sockaddr_in client_addr_;
};
REGISTER_MESSAGE_COMMUNICATE_ENTITY(udp_unicast_server, "udp.unicast.server");

#endif /* SRC_UDP_UNICAST_SERVER_HPP_ */

6.udp Unicast client

#ifndef SRC_UDP_UNICAST_CLIENT_HPP_
#define SRC_UDP_UNICAST_CLIENT_HPP_
#include "message_communicate_entity.hpp"
class udp_unicast_client : public message_communicate_entity {
public:
	udp_unicast_client() {
		sock_fd_ = -1;
		port_ = 27790;
		unicast_address_ = "127.0.0.1";
		memset(&client_addr_, 0, sizeof(client_addr_));
	}
	~udp_unicast_client() {
		if (sock_fd_ >= 0) {
			close(sock_fd_);
		}
	}
public:
	inline bool init() override {
		return init_sock_fd();
	}
	inline bool init_sock_fd() {
		sock_fd_ = socket(AF_INET, SOCK_DGRAM, 0);
		return sock_fd_ >= 0;
	}
	inline void set_port(int port) {
		port_ = port;
	}
	inline void set_unicast_address(const char *address) {
		unicast_address_ = address;
	}
	virtual int send(const char *buf, int len) override {
		struct sockaddr_in dest_addr = {0};
		dest_addr.sin_family = AF_INET;
		dest_addr.sin_port = htons(port_);
		dest_addr.sin_addr.s_addr = inet_addr(unicast_address_);
		return sendto(sock_fd_, buf, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
	}
	virtual int recv(char *recv_buf, int buf_len) override {
		if (buf_len <= 0 || buf_len > BUFSIZ) {
			return -1;
		}
		char buf[BUFSIZ] = "";
		socklen_t size = sizeof(struct sockaddr);
		int len = recvfrom(sock_fd_, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr_, &size);
		if (len <= BUFSIZ && len > 0) {
			len = min(len, buf_len);
			memcpy(recv_buf, buf, len);
		}
		return len;
	}
private:
	int sock_fd_;
	int port_;
	const char *unicast_address_;
	struct sockaddr_in client_addr_;
};
REGISTER_MESSAGE_COMMUNICATE_ENTITY(udp_unicast_client, "udp.unicast.client");

#endif /* SRC_UDP_UNICAST_CLIENT_HPP_ */

7. Test Code

void send_broadcast_thread(const char *buf) {
	this_thread::sleep_for(chrono::milliseconds(100));
	auto client = message_communicate_entity_maker::make_unique_ptr("udp.broadcast.client");
	if (client->init() >= 0) {
		reinterpret_cast<udp_broadcast_client *>(client.get())->set_broadcast_address(zeg_config::get_instance().robot_broadcast_address.c_str());
		client->send(buf, strlen(buf));
	}
}
void recv_broadcast_thread() {
	auto server = message_communicate_entity_maker::make_unique_ptr("udp.broadcast.server");
	if (server->init()) {
		server->recv(udp_recv_buf, sizeof(udp_recv_buf));
	}
}
TEST_CASE("testing udp broadcast entity") {
	const char *buf = "hello world, I am udp broadcast test.";
	thread th0(send_broadcast_thread, buf);
	thread th1(recv_broadcast_thread);
	th0.join();
	th1.join();
	CHECK(0 == strcmp(buf, udp_recv_buf));
}

 

Guess you like

Origin blog.csdn.net/wangzhicheng2013/article/details/93023890