C++ Network Programming: Mastering complexity with ACE and patterns

Douglas C. Schmidt, Stephen D. Huston

Mentioned 6

As networks, devices, and systems continue to evolve, software engineers face the unique challenge of creating reliable distributed applications within frequently changing environments. C++ Network Programming, Volume 1, provides practical solutions for developing and optimizing complex distributed systems using the ADAPTIVE Communication Environment (ACE), a revolutionary open-source framework that runs on dozens of hardware platforms and operating systems. This book guides software professionals through the traps and pitfalls of developing efficient, portable, and flexible networked applications. It explores the inherent design complexities of concurrent networked applications and the tradeoffs that must be considered when working to master them. C++ Network Programming begins with an overview of the issues and tools involved in writing distributed concurrent applications. The book then provides the essential design dimensions, patterns, and principles needed to develop flexible and efficient concurrent networked applications. The book's expert author team shows you how to enhance design skills while applying C++ and patterns effectively to develop object-oriented networked applications. Readers will find coverage of: C++ network programming, including an overview and strategies for addressing common development challenges The ACE Toolkit Connection protocols, message exchange, and message-passing versus shared memory Implementation methods for reusable networked application services Concurrency in object-oriented network programming Design principles and patterns for ACE wrapper facades With this book, C++ developers have at their disposal the most complete toolkit available for developing successful, multiplatform, concurrent networked applications with ease and efficiency.

More on Amazon.com

Mentioned in questions and answers.

I haven't done work in C/C++ for a little bit and was just wondering what people's favorite cross platform libraries are to use.

I'm looking for something that is a good quick and dirty library as well as a library that is a little more robust. Often those are two different libraries and that's okay.

Aggregated List of Libraries

Hey, I'm a newcomer to using C++ but have got a general Idea of its syntax and useability. I want to learn how to communicate over networks through C++ programming though but I can't seem to find any tutorials for C++ specifically. Does anyone know any good resources to learn about networking with C++ or what I should start with?

Thanks a bunch, Dan

Could someone point to preferred references/books for C++ or language-agnostic server application development?

I do have some experience in this sphere, but I would like to know more and, obviously, knowledge may come from reading the corresponding books :)

There is few good books on the ACE C++ framework developed by Douglas C. Schmidt, for example C++ Network Programming: Resolving Complexity Using ACE and Patterns v.1: Resolving Complexity Using ACE and Patterns Vol 1

What is the best way to use sockets on the Windows platform?

Basic sockets I guess, TCP/IP. Maybe for a chat client, or just for learning.

Could someone give me an example of WININET usage?

maybe ftpgetfile()

If you are looking to use this as a learning experience I would also look at ACE. A C++ cross platform framework that implements a lot of the patterns discussed in Patterns for Concurrent Network and Networked Objects. The author has also written on ACE as well (see here).

This question is about the use of ACE mutexes. Below is a rather lengthy minimal example, which works as follows:

The code starts several threads and stops them after 10 seconds. Each of the threads tries to acquire a mutex and keeps it until its termination. There are two kinds of threads. The first kind uses a global variable while the second kind uses a local variable. All mutexes have the same name. Since the threads share a single process, I expect that one acquires the mutex while the others must wait until this thread terminates.

Observation: While the global mutex always works as expected, the ACE_Thread_Mutex and ACE_Recursive_Thread_Mutex fail if used as a local variable. The local objects seem to be distinct mutexes despite the shared name. Why is that? Is there a thread mutex which works similar to a process mutex. I should mention that I use ACE on Windows.

My second question is whether a mutex should be an object or a pointer to an object. Is there any difference in behavior? Of course the pointer can be shared, while the object is easier to handle. Hence I prefer objects, but then thread mutexes do not seem to work like process mutexes.

Thank you very much for some insight.

PS: I am aware that I can always emulate a thread mutex using a process mutex with prepended process ID or something similar. This is not what my questions aim at.

#include <iostream>
#include <sstream>

#include <ace/Process_Mutex.h>
#include <ace/Task.h>
#include <ace/Semaphore.h>

#define LOG(msg) std::cout << msg << std::endl;

#define NAME_MUTEX_THREAD "MY_UNIQUE_MUTEX"

// switch between different mutex types
// #define MUTEX_DECL(var, name) ACE_Thread_Mutex var(name);
// #define MUTEX_DECL(var, name) ACE_Recursive_Thread_Mutex var(name);
#define MUTEX_DECL(var, name) ACE_Process_Mutex var(name);
// #define MUTEX_DECL(var, name) ACE_Semaphore var(1, USYNC_THREAD, name);
// #define MUTEX_DECL(var, name) ACE_Semaphore var(1, USYNC_PROCESS, name);

ACE_Thread_Manager * g_pThreadManager;

MUTEX_DECL(g_oMutex, NAME_MUTEX_THREAD);

using namespace std;

std::string getThreadLogPrefix(void)
{
  ACE_thread_t thisThread = ACE_OS::thr_self();
  const int iProcessID = ACE_OS::getpid();
  const int iThreadID = thisThread;

  ostringstream convert;
  convert <<"P"<<iProcessID<<"T"<<iThreadID;

  return convert.str();
}


ACE_THR_FUNC_RETURN threadLocalMutexRace(void * par)
{
  const ACE_thread_t thisThread = ACE_OS::thr_self();
  const string strLog = getThreadLogPrefix() + "_threadLocalMutexRace: ";

  MUTEX_DECL(oMutex, NAME_MUTEX_THREAD);

  LOG(strLog<<"Start");

  LOG(strLog<<"Try to acquire mutex");
  int irc = oMutex.acquire();
  if (irc == -1) {
    LOG(strLog<<"Mutex not acquired (code "<<irc<<").");
    return 0;
  }

  LOG(strLog<<"Mutex acquired (code "<<irc<<").");

  while(ACE_Thread_Manager::instance()->testcancel(thisThread) == 0){
    ;
  }

  LOG(strLog<<"Stop");
  oMutex.release();
  LOG(strLog<<"Mutex released.");

  return 0;
}


ACE_THR_FUNC_RETURN threadMutexRace(void * par)
{
  const ACE_thread_t thisThread = ACE_OS::thr_self();
  const string strLog = getThreadLogPrefix() + "_threadMutexRace: ";

  LOG(strLog<<"Start");

  LOG(strLog<<"Try to acquire mutex");
  int irc = g_oMutex.acquire();
  if (irc == -1) {
    LOG(strLog<<"Mutex not acquired (code "<<irc<<").");
    return 0;
  }

  LOG(strLog<<"Mutex acquired (code "<<irc<<").");

  while(ACE_Thread_Manager::instance()->testcancel(thisThread) == 0){
    ;
  }

  LOG(strLog<<"Stop");
  g_oMutex.release();
  LOG(strLog<<"Mutex released.");

  return 0;
}


int main(int argc, char * argv[])
{
  ACE::init(); 
  g_pThreadManager = new ACE_Thread_Manager();

  const unsigned int uiNumThreadMutexRace = 3;


  if (g_pThreadManager)
  {
    LOG("*******************************************************************");
    LOG("Start threads...");

    for (unsigned int i = 0; i < uiNumThreadMutexRace; ++i)
    {
      g_pThreadManager->spawn((ACE_THR_FUNC)threadMutexRace, nullptr);
    }

    for (unsigned int i = 0; i < uiNumThreadMutexRace; ++i)
    {
      g_pThreadManager->spawn((ACE_THR_FUNC)threadLocalMutexRace, nullptr);
    }

    ACE_OS::sleep(10);

    LOG("Stop threads...");
    g_pThreadManager->cancel_all();
    g_pThreadManager->wait();
    LOG("All threads stopped.");
    LOG("*******************************************************************");
  }

  delete g_pThreadManager;
  g_pThreadManager = nullptr;

  return 0;
}

The name is not an unique identifier for the ACE thread mutexes. You have to make sure that both threads use the same ACE thread mutex instance, by using a local variable both have its own instance which both can lock independently. Normally in C++ you put the mutex as class member so that you can use it in the various operations of that class. I would recommend to read chapter 10 of the C++ Network Programming volume 1 book.

This question was asked in multiple choice question in an interview.

Network programming can be done in which of the following languages?

a) C
b) C++
c) Java
d) Pascal

I think it is possible to network programming in each of these technology.

Guys anyone know .....what would be the correct answer?

Indeed all of them (just perhaps Pascal is not a good choice), just take a look at these books :

Network Programming in C

C++ Network Programming, Volume I: Mastering Complexity with ACE and Patterns

Java Network Programming, Third Edition

A question with resources available on SO: Sockets in pascal