Click here to Skip to main content
13,248,343 members (44,975 online)
Click here to Skip to main content
Add your own
alternative version

Stats

8.8K views
188 downloads
16 bookmarked
Posted 1 Dec 2016

Real time collaboration: A quick C++ Windows library with RDC support

, 19 Jun 2017
Rate this:
Please Sign up or sign in to vote.
Create collaborating projects easily
 

Introduction

This is an old dream. I always wanted to create apps that allow all of my users (clients, students, teachers) to work on a same file and exchange realtime information in an efficient way.

Perhaps it is your dream too. If so, keep reading.

Background

The code is a collection of some of my own libraries:

  • DIFF library, using Remote Differential Compression for more efficient updates.
  • RWMutex and tlock, my own synchronization objects to provide complex locks.
  • Some of my own small helpers, including TEVENT and XSOCKET, and
  • collab.hpp, the library described here.

The library is a client-server mode. The server listens to an accessible TCP port and the clients connect to the server which keeps all the shared documents locally or in memory. If a client updates the document, the server notifies all other clients with the update data.

Client Authentication

The library provides an abstract way to authenticate either the server or the clients, via the AUTH class. This class' member function Do() returns a HRESULT. On E_PENDING, the function is called again. On successful authentication the function must return an S_ code, and on failure it must return an E_ code.

The library provides an ANYAUTH class which simply returns S_OK for testing purposes. You may pass your own authentication mechanism.

Client Authorization

The same AUTH class Do() function can return S_FALSE when it is also passed a document's CLSID. In this case the file can only be opened for reading, but client updates to this file will fail.

The library provides an ANYAUTH class which simply returns S_OK for testing purposes. You may pass your own authorization mechanism.

The document

Each document is identified uniquely by a CLSID. Each server can host unlimited documents, and each client can manipulate any number of documents.

The server also maintains the current signature of all the documents opened by a client, so the serve can know how to update a client when another client has updated a shared file.

The server part

The server part is contained in the class SERVER, which contains a list of all documents and a list of all connected clients. Each client can open any number of documents.

//
COLLAB::ANYAUTH auth;
COLLAB::SERVER s(&auth, 8765,true); // Port 8765, and true to use filesystem instead of in-memory docs
s.Start(); // Start the server
...
...
...
s.End(); // Ends the server when we want to close it
//

You call SERVER::Start() which returns S_OK on success. The server runs in a background thread. When a client connects, a new thread is created. The client performs requests to the server as follows:

  • Create or open a document
  • Close a document
  • Get a documents current signature
  • Update a document

When a document is updated, all other clients that have opened that document are updated via the SERVER::UpdateClientsOfDocument() method.

You can call also:

  • void ForceUpdateDocument(GUID c), to force updating a document to all clients.
  • shared_ptr<DOCUMENT> GetDocument(GUID c), to get a pointer to the document (if you want to lock it and edit it outside the clients).

End the server using End(). This method shuts down all clients immediately.

The client part

You need first an ON structure, which provides notification when an update is received:

class ON
    {
    public:
        virtual void Update(CLSID cid,const char* d,size_t sz) = 0;
    };

The first parameter is the CLSID of the document being updated. The rest are the new data for the document (a DIFF object)

To reconstruct the entire document we can use this helper in a multithreaded COM environment:

void RecoFromDiff(const char* d, size_t sz, const char* e, size_t sze, vector<char>& o)
    {
    DIFFLIB::DIFF diff;
    DIFFLIB::MemoryRdcFileReader r1(e, sze);
    DIFFLIB::MemoryRdcFileReader diffi(d, sz);

    DIFFLIB::MemoryDiffWriter dw;
    diff.Reconstruct(&r1, &diffi, 0, dw);
    o = dw.p();
    }

Parameters e and sze are the current byte array and size of our document, and d and sz are the diff. The function reconstructs the complete object in the vector<char> array.

Each client is represented by the COLLAB::CLIENT class, containing references to all documents, and a vector<> of ON notification classes:

//
COLLAB::ANYAUTH auth;
COLLAB::CLIENT c1(&auth);
MYON on; // some class that implements Update() of COLLAB::ON 
c1.AddOn(&on); // check below for ON class
c1.Connect("localhost",8765);
c1.Open(DOCUMENT_GUID); // If guid does not exist, server creates such a document
//
...
...
...
c1.Close(DOCUMENT_GUID);
...
...
...
c1.RemoveOn(&on);
c1.Disconnect();

If the document exists, the client is immediately updated from the server (note that, if you have your own updated version of the client you must push it to the server after this initial update).

When you want to put updates to the server, you call CLIENT::Put():

HRESULT Put(GUID g, const char* d,size_t sz);

The function requests the documents signature from the server, then only uploads a diff to it, minimizing network usage.

The files

The zip contains:

  • A complete collaboration demo solution with prebuild executable and sources.
  • diff.h and collab.hpp are all you need to include in your own projects.
  • Two prebuild binaries, server.exe and notepad.exe which you can use to create multiple editors of the same file.

History

20 - 6 - 2017: Updated RWMutex, tlock and the library.

1 - 12 - 2016: First Release.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Michael Chourdakis
Engineer
Greece Greece
I'm working in C++, PHP , Java, Windows, iOS and Android.

I 've a PhD in Digital Signal Processing and I specialize in Pro Audio applications.

My home page: http://www.michaelchourdakis.com

You may also be interested in...

Pro

Comments and Discussions

 
QuestionSome info missing... Pin
Dewey14-Nov-17 9:37
memberDewey14-Nov-17 9:37 
  1. A diagram is worth a thousand explanations
  2. A picture of a sample session is worth a thousand words
However, if I had to choose, I'd take just a picture for starters, but thanks for sharing anyway.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.171114.1 | Last Updated 19 Jun 2017
Article Copyright 2016 by Michael Chourdakis
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid