diff --git a/Common/Gmsh.cpp b/Common/Gmsh.cpp
index 38af13f28624f90d62529125bb75e6026e691994..c676b9732fce2e08207c377ebc5249cb7551934c 100644
--- a/Common/Gmsh.cpp
+++ b/Common/Gmsh.cpp
@@ -16,7 +16,7 @@
 #include "CommandLine.h"
 #include "OS.h"
 #include "Context.h"
-#include "ConnectionManager.h"
+#include "onelab.h"
 #include "robustPredicates.h"
 
 #if defined(HAVE_MESH)
@@ -252,8 +252,9 @@ int GmshFLTK(int argc, char **argv)
 
   // listen to external solvers
   if(CTX::instance()->solver.listen){
-    ConnectionManager::get(-1)->name = "unknown";
-    ConnectionManager::get(-1)->run("");
+    onelab::localNetworkClient *c = new onelab::localNetworkClient("Listen", "");
+    onelab::server::instance()->registerClient(c);
+    c->run("");
   }
 
   // loop
diff --git a/Common/onelab.h b/Common/onelab.h
index 42ac105f3e5abd0c0e6e6ed5ef0edfdeac6aea9c..0f6e353ee7bdbd1f694bcea889c55da966254a01 100644
--- a/Common/onelab.h
+++ b/Common/onelab.h
@@ -449,10 +449,14 @@ namespace onelab{
   protected:
     // the name of the client
     std::string _name;
+    // the id of the client, used to create a unique socket for this client
+    int _id;
   public:
     client(const std::string &name) : _name(name){}
     virtual ~client(){}
     std::string getName(){ return _name; }
+    void setId(int id){ _id = id; }
+    int getId(){ return _id; }
     virtual bool run(const std::string &what){ return false; }
     virtual bool isNetworkClient(){ return false; }
     virtual bool kill(){ return false; }
@@ -507,6 +511,7 @@ namespace onelab{
     {
       if(_clients.count(c->getName())) return false;
       _clients[c->getName()] = c;
+      c->setId(_clients.size());
       return true;
     }
     typedef std::map<std::string, client*>::iterator citer;
@@ -569,15 +574,19 @@ namespace onelab{
     std::string _commandLine;
     // pid of the remote network client
     int _pid;
+    // underlying GmshServer
+    GmshServer *_gmshServer;
   public:
     localNetworkClient(const std::string &name, const std::string &commandLine)
-      : localClient(name), _commandLine(commandLine), _pid(-1) {}
+      : localClient(name), _commandLine(commandLine), _pid(-1), _gmshServer(0) {}
     virtual ~localNetworkClient(){}
     virtual bool isNetworkClient(){ return true; }
     const std::string &getCommandLine(){ return _commandLine; }
     void setCommandLine(const std::string &s){ _commandLine = s; }
     int getPid(){ return _pid; }
     void setPid(int pid){ _pid = pid; }
+    GmshServer const *getServer(){ return _gmshServer; }
+    void setServer(GmshServer *server){ _gmshServer = server; }
     virtual bool run(const std::string &what);
     virtual bool kill();
   };
diff --git a/Fltk/onelabWindow.cpp b/Fltk/onelabWindow.cpp
index a955597dc10c25c8e710449175178afabf2466e9..c06db6bac0bd66c320d4f32c5495bc14b348bfa8 100644
--- a/Fltk/onelabWindow.cpp
+++ b/Fltk/onelabWindow.cpp
@@ -46,8 +46,9 @@ class onelabGmshServer : public GmshServer{
       if(timeout > 0 && GetTimeInSeconds() - start > timeout)
         return 2; // timout
 
-      if(_client->getPid() < 0)
-        return 1; // process has been killed
+      if(_client->getPid() < 0 ||
+         (_client->getCommandLine().empty() &&  !CTX::instance()->solver.listen))
+        return 1; // process has been killed or we stopped listening
 
       // check if there is data (call select with a zero timeout to
       // return immediately, i.e., do polling)
@@ -64,6 +65,7 @@ class onelabGmshServer : public GmshServer{
       else{ 
         // an error happened
         _client->setPid(-1);
+        _client->setServer(0);
         return 1;
       }
     }
@@ -72,29 +74,38 @@ class onelabGmshServer : public GmshServer{
 
 bool onelab::localNetworkClient::run(const std::string &what)
 {
+ new_connection:
   _pid = 0;
+  _gmshServer = 0;
+
   onelabGmshServer *server = new onelabGmshServer(this);
- 
+
   std::string sockname;
+  std::ostringstream tmp;
   if(!strstr(CTX::instance()->solver.socketName.c_str(), ":")){
     // Unix socket
-    std::ostringstream tmp;
-    tmp << CTX::instance()->homeDir << CTX::instance()->solver.socketName;
+    tmp << CTX::instance()->homeDir << CTX::instance()->solver.socketName << getId();
     sockname = FixWindowsPath(tmp.str());
   }
   else{
     // TCP/IP socket
-    sockname = CTX::instance()->solver.socketName;
-    // if only the port is given, prepend the host name
-    if(sockname.size() && sockname[0] == ':')
-      sockname = GetHostName() + sockname;
+    if(CTX::instance()->solver.socketName.size() && 
+       CTX::instance()->solver.socketName[0] == ':')
+      tmp << GetHostName(); // prepend hostname if only port is given
+    tmp << CTX::instance()->solver.socketName << getId();
+    sockname = tmp.str();
   }
 
-  std::string prog = FixWindowsPath(_commandLine);
-  std::string command = prog + " " + what +  " -onelab " + sockname;
+  std::string command = FixWindowsPath(_commandLine);
+  if(command.size()){
+    command += " " + what +  " -onelab " + sockname;
 #if !defined(WIN32)
-  command += " &";
+    command += " &";
 #endif
+  }
+  else{
+    Msg::Info("Listening on socket '%s'", sockname.c_str());
+  }
 
   int sock;
   try{
@@ -116,10 +127,15 @@ bool onelab::localNetworkClient::run(const std::string &what)
 
   while(1) {
 
-    if(_pid < 0) break;
+    if(_pid < 0 || (command.empty() && !CTX::instance()->solver.listen))
+      break;
     
     int stop = server->NonBlockingWait(sock, 0.1, 0.);
-    if(stop || _pid < 0) break;
+
+    if(stop || _pid < 0 || (command.empty() && !CTX::instance()->solver.listen))
+      break;
+
+    double timer = GetTimeInSeconds();
     
     int type, length, swap;
     if(!server->ReceiveHeader(&type, &length, &swap)){
@@ -136,9 +152,11 @@ bool onelab::localNetworkClient::run(const std::string &what)
     switch (type) {
     case GmshSocket::GMSH_START:
       _pid = atoi(message.c_str());
+      _gmshServer = server;
       break;
     case GmshSocket::GMSH_STOP:
       _pid = -1;
+      _gmshServer = 0;
       break;
     case GmshSocket::GMSH_PARAMETER:
       {
@@ -215,7 +233,11 @@ bool onelab::localNetworkClient::run(const std::string &what)
       ParseString(message);
       drawContext::global()->draw();
       break;
-    /* FIXME need to change PViewDataRemote to work without ConnectionManager
+    case GmshSocket::GMSH_SPEED_TEST:
+      Msg::Info("got %d Mb message in %g seconds",
+                length / 1024 / 1024, GetTimeInSeconds() - timer);
+      break;
+    /* FIXME PViewDataRemote should store the onelab::localNetworkClient
     case GmshSocket::GMSH_VERTEX_ARRAY:
       {
         int n = PView::list.size();
@@ -233,10 +255,17 @@ bool onelab::localNetworkClient::run(const std::string &what)
     FlGui::instance()->check();
   }
 
+  _gmshServer = 0;
   server->Shutdown();
   delete server;
 
   Msg::StatusBar(2, true, "Done running '%s'", _name.c_str());
+
+  if(command.empty()){
+    Msg::Info("Client disconnected: starting new connection");
+    goto new_connection;
+  }
+
   return true;
 }
 
@@ -336,7 +365,10 @@ void onelab_cb(Fl_Widget *w, void *data)
   for(onelab::server::citer it = onelab::server::instance()->firstClient();
       it != onelab::server::instance()->lastClient(); it++){
     onelab::client *c = it->second;
-    if(c->getName() == "Gmsh") continue;
+    if(c->getName() == "Gmsh" || // local Gmsh client
+       c->getName() == "Listen" || // unknown client connecting through "-listen"
+       c->getName() == "GmshRemote") // distant post-processing Gmsh client
+      continue;
     std::string what = FlGui::instance()->onelab->getModelName();
     if(action == "initial check" || action == "check"){
       c->run(what);
@@ -609,4 +641,3 @@ void solver_cb(Fl_Widget *w, void *data)
 }
 
 #endif
-
diff --git a/utils/solvers/c++/GmshSocket.h b/utils/solvers/c++/GmshSocket.h
index 0f67ad37b67730c14ba55b37f8efcd904a5d25ef..fbabdb473c0a91d661519225529da6923e670964 100644
--- a/utils/solvers/c++/GmshSocket.h
+++ b/utils/solvers/c++/GmshSocket.h
@@ -61,21 +61,23 @@ class GmshSocket{
   // receive data from a machine with a different byte ordering, and
   // we swap the bytes in the payload)
   enum MessageType{ 
-    GMSH_START        = 1,
-    GMSH_STOP         = 2,
-    GMSH_INFO         = 10,
-    GMSH_WARNING      = 11,
-    GMSH_ERROR        = 12,
-    GMSH_PROGRESS     = 13,
-    GMSH_MERGE_FILE   = 20,
-    GMSH_PARSE_STRING = 21,
-    GMSH_VERTEX_ARRAY = 22,
-    GMSH_SPEED_TEST   = 30,
-    GMSH_OPTION_1     = 100,
-    GMSH_OPTION_2     = 101,
-    GMSH_OPTION_3     = 102,
-    GMSH_OPTION_4     = 103,
-    GMSH_OPTION_5     = 104};
+    GMSH_START           = 1,
+    GMSH_STOP            = 2,
+    GMSH_INFO            = 10,
+    GMSH_WARNING         = 11,
+    GMSH_ERROR           = 12,
+    GMSH_PROGRESS        = 13,
+    GMSH_MERGE_FILE      = 20,
+    GMSH_PARSE_STRING    = 21,
+    GMSH_VERTEX_ARRAY    = 22,
+    GMSH_PARAMETER       = 23,
+    GMSH_PARAMETER_QUERY = 24,
+    GMSH_SPEED_TEST      = 30,
+    GMSH_OPTION_1        = 100,
+    GMSH_OPTION_2        = 101,
+    GMSH_OPTION_3        = 102,
+    GMSH_OPTION_4        = 103,
+    GMSH_OPTION_5        = 104};
  protected:
   // the socket descriptor
   int _sock;
@@ -204,6 +206,11 @@ class GmshSocket{
     }
     return 0;
   }
+  int ReceiveMessage(int len, void *buffer)
+  {
+    if(_ReceiveData(buffer, len) == len) return 1;
+    return 0;
+  }
   // str should be allocated with size (len+1)
   int ReceiveString(int len, char *str)
   {
@@ -365,7 +372,7 @@ class GmshServer : public GmshSocket{
     }
 
     if(command && strlen(command)){
-      SystemCall(command); // Start the solver
+      SystemCall(command); // start the solver
     }
     else{
       timeout = 0.; // no command launched: don't set a timeout
diff --git a/utils/solvers/c++/interactive.cpp b/utils/solvers/c++/interactive.cpp
index ed55291257d97b1e339202f61461a5d83b211015..b42ee0136fbcc2cf357dd1ac4f4b515c2139fc2d 100644
--- a/utils/solvers/c++/interactive.cpp
+++ b/utils/solvers/c++/interactive.cpp
@@ -25,7 +25,7 @@ class GmshInteractiveClient{
     _client.Stop();
     _client.Disconnect();
   }
-  void read(char *prompt)
+  void read(const char *prompt)
   {
     // pre-load a few commands in the history:
     add_history("lc = 1.;");