.NET Rangers

I am proud to announce that the .NET Rangers community is back ! We have 3 MVP !

We have a blog : http://www.dotnetrangers.org and a Twitter account:

.NET Rangers @RangersNet

Members of the community:

  • Jean-Baptiste B. Sogeti
  • Cdric G. Sogeti
  • Jean-Nicolas B. Sogeti
  • Guilhem M. C-S
  • Cdric T. Sogeti
  • Keelan C. Sogeti
  • Eva D. Neos-SDI
  • Frederic S. Sydev
  • Michel F. Indep
  • Jean-Nol G. Indep
  • Christophe P. Neos-SDI

Article in Technical Magazine Programmez N° 219 – June 2018

May be in next June edition of french magazine Programmez, an article about creating a Windows Service. All the plumbing ! The second part will explain how to host a deamon inside and respond to external communication.

Creating the Ping feature for a middleware

For my clustering master/worker nodes, I have put a Ping thread:

To be production code, I will protect the vector _nodes. It’s a multi-thread appz so… it needs to be done.

void MyServer::ActivatePingThread()
	DWORD dwThreadId = 0;
	HANDLE hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &MyServer::PingThread, NULL, 0, &dwThreadId);

void MyServer::PingThread(LPVOID param)
	while (TRUE)


		std::shared_ptr<NodeAttributes> pObj = nullptr;

		for (auto itr = _nodes.begin(); itr != _nodes.end(); itr++)
			pObj = *itr;

			TCHAR sz[255];
			_stprintf(sz, _T("http://%s:%s/MyServer/LMDB/"), pObj->_server.c_str(), pObj->_port.c_str());

			std::wstring address = sz;

			http_client client(address);

			std::wostringstream buf;
			buf << _T("?request=") << _T("ping");

			http_response response;

				wcout << _T("Ping testing ip:") << pObj->_server.c_str() << _T(" on port:") << pObj->_port.c_str() << endl;
				response = client.request(methods::GET, buf.str()).get();
				wcout << response.to_string() << endl;
			catch (...)
				// Something goes wrong !
				pObj->_isActive = false;
				*itr = pObj;

			json::value jdata = json::value::array();
			jdata = response.extract_json().get();

			if (jdata.is_null())
				std::wcout << _T("no JSON data...") << std::endl;

				// Something goes wrong !
				pObj->_isActive = false;
				*itr = pObj;

			PingData data = PingData::FromJSON(jdata.as_object());

			if (data.status == _T("OK"))
				// Normal behaviour
				// Something goes wrong !
				pObj->_isActive = false;
				*itr = pObj;


Creating a cluster of nodes in C++ REST

Creating a cluster of nodes…

I have a server appz that can be forked either to start nodes or the main server controller node.

When a node starts, its register with the node controller (master) giving its ip, its port and a name.

The node controller keeps that information in a std::vector<T>.

There is also an admin tool to send commands and see what’s in the master node.

start myserver

start myserver 7002 node node_1

start myserver 7003 node node_2

start myserver 7004 node node_3

start myclient 7001

The first myserver instance is the controller node (master). All others instances are worker nodes on a dedicated ip/port.

They all register with master. Master node will allow a node to be active when a client request for a node…

An admin tool allow to known when it happened:

F:DevGitHubLMDBLMDBWindowsx64Debug>admin 7001


Enter a command:?request=show-nodes

HTTP/1.1 200 OK

Content-Length: 0

Date: Sat, 19 May 2018 15:25:52 GMT

Server: Microsoft-HTTPAPI/2.0

Message GET /MyServer/LMDB/?request=show-nodes HTTP/1.1

Connection: Keep-Alive


User-Agent: cpprestsdk/2.10.2

Relative URI /?request=show-nodes

Query request show-nodes

Request show-nodes


Active:0 Server: Port:7002 Name:node_1

Active:0 Server: Port:7003 Name:node_2

Active:0 Server: Port:7004 Name:node_3

As we can see, there are registered nodes but no active one yet.

If I start a client asking for a worker node: myclient 7001

The server reacts:

Relative URI /?request=get-node&name=cache_v1

Query name cache_v1

Query request get-node

Request get-node

name cache_v1



If I ask my admin tool to show nodes:

Relative URI /?request=show-nodes

Query request show-nodes

Request show-nodes


Active:1 Server: Port:7002 Name:cache_v1

Active:0 Server: Port:7003 Name:node_2

Active:0 Server: Port:7004 Name:node_3

There is one active node. The name is submitted by the client for an LMDB database names cache_v1.

.NET Ranger – The community is reborn !

I am proud to announce that the .Net Rangers are back !

The web site www.dotnetrangers.org is live.

We are a community of Windows Experts in development and infrastructure. Stay tuned !

Give the extra class for HTTP Server !

Here is the code :


#pragma once

class LMDBData
	virtual ~LMDBData();

	MDB_env * m_env;
	MDB_dbi m_dbi;
	MDB_txn * m_txn;
	MDB_val m_key;
	MDB_val m_data;
	MDB_stat m_mst;

#include "StdAfx.h"
#include "LMDBData.h"



Give me the main of the HTTP Server

Here is the code :

#include "stdafx.h"
#include "MyServer.h"

using namespace web;
using namespace http;
using namespace utility;
using namespace http::experimental::listener;

std::unique_ptr<MyServer> g_http;

std::wstring GetIP()

	// Init WinSock
	WSADATA wsa_Data;
	int wsa_ReturnCode = WSAStartup(0x101, &wsa_Data);

	// Get the local hostname
	char szHostName[255];
	gethostname(szHostName, 255);
	struct hostent *host_entry;
	host_entry = gethostbyname(szHostName);
	char * szLocalIP;
	szLocalIP = inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list);

	std::wstring ip = A2W(szLocalIP);
	return ip;

int wmain(int argc, wchar_t *argv[])
    utility::string_t port = U("7001");
	std::wstring defaultAddress = _T("localhost");
	if(argc == 2)
        port = argv[1];
	if (argc == 3)
		defaultAddress = argv[1];
		port = argv[2];

	std::wstring ip = GetIP();
	std::wcout << L"IP : " << ip << std::endl;

	std::wstring address = _T("http://");
	address.append(ip); // defaultAddress); //ip
	http::uri uri = http::uri(address);
	auto addr = uri.to_string();

	// Create the server instance

	std::wcout << L"Server " << addr << std::endl;

	g_http = std::unique_ptr<MyServer>(new MyServer(addr));

	ucout << utility::string_t(U("Listening for requests at: ")) << addr << std::endl;
	std::cout << "Press ENTER to exit." << std::endl;
    std::string line;
    std::getline(std::cin, line);

	return 0;