hmbdc
simplify-high-performance-messaging-programming
chat.cpp
//this is to show how to use hmbdc to write a simple group chat application
//the app join a chat group and start to have group chat
//to run:
//./chatter local-ip chat-group-name my-name
//to build:
//g++ example/chat.cpp -g -std=c++1y -Wall -Werror -pthread -Ipath-to-hmbdc-lib-include path-to-hmbdc-lib/libhmbdc.a /usr/local/lib/libboost_regex.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_iostreams.a -lpthread -lrt -o /tmp/chatter
//
#include "hmbdc/app/tcpcast/NetContext.hpp" //use tcpcast for communication
#include <iostream>
#include <string>
#include <memory>
#include <unistd.h>
using namespace std;
using namespace hmbdc::app;
//this is the message going back and forth carrying text conversations - 1000 char max
struct ChatMessage
: hasTag<1001> { //each message needs a unique tag - 16 bit user tag starting from 1001, 0-1000 is reserved
char id[16]; //chatter
char msg[1000]; //1000 char max per chat message
};
using MyContext = Context<sizeof(ChatMessage)>;
using NetCtx = tcpcast::NetContext;
struct Chatter
: Client<Chatter, ChatMessage> {
Chatter(char const* id)
: id_(id){}
void handleMessageCb(ChatMessage const& m) {
cout << m.id << ": " << m.msg << endl;
}
private:
string id_;
};
int main(int argc, char** argv) {
using namespace std;
if (argc != 4) {
cerr << argv[0] << " local-ip chat-group-name my-name" << endl;
cerr << "multicast should be enabled on local-ip network" << endl;
return -1;
}
auto ifaceAddr = argv[1];
auto chatGroup = argv[2];
auto myId = argv[3];
Config config; //other config values are default
config.put("ifaceAddr", ifaceAddr);//which interface to use for communication
config.put("loopback", true); //could be chatting on the same machine
MyContext ctx;
SingletonGuardian<NetCtx> g; //RAII for tcpcast::NetContext resources
auto& net = NetCtx::instance(); //this is the interface for network(tcpcast) communication functions
// we send out messages, need a send engine
auto sengine = net.createSendTransportEngine(config
, sizeof(ChatMessage)); //maximum size of the message the engine can send out
// we receive messages, need a receive engine
auto rengine = net.createRecvTransportEngine(config
, ctx.buffer()); //put the incoming messsage into ctx's buffer, so Chatter can see
ctx.start(1 //start ctx with just 1 thread in the pool to power everything
, 0x01); //pin the pool thread on first core
//add engine clients into pool to run
ctx.addToPool(*rengine);
ctx.addToPool(*sengine);
Chatter chatter(myId);
ctx.addToPool(chatter); //add the chatter client too
//now the network is set up
//subscribe to the topic
//and get a sender for the topic
Topic t(chatGroup);
net.listenTo(t);
auto s = net.getSender(t);
//we can read the user's input and send messages out now
string line;
ChatMessage m;
strncpy(m.id, myId, sizeof(m.id));
cout << "start type a message" << endl;
cout << "ctrl-d to terminate" << endl;
while(getline(cin, line)) {
strncpy(m.msg, line.c_str(), sizeof(m.msg));
s->send(m);
}
net.stopListenTo(t);
}