diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 3da6f3546b829920ba6ea664b6fefc737129f5c1..234f7091c1fd7541f23b39af96054d91c57dd0f8 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -95,7 +95,7 @@ StringXString MeshOptions_String[] = {
 StringXString SolverOptions_String[] = {
   { F|O, "SocketName" , opt_solver_socket_name , 
 #if defined(WIN32) && !defined(__CYGWIN__)
-    "127.0.0.1:44122" , // use TCP/IP sockets by default on "pure" Windows
+    ":44122" , // use TCP/IP sockets by default on Windows
 #else
     ".gmshsock" , // otherwise use Unix sockets by default
 #endif
diff --git a/Common/OS.cpp b/Common/OS.cpp
index b8fd20a55fe376adefb09686ab5f74832376b30f..5f9ca684ca9b2ccae48615eb0faa720c28da4e2b 100644
--- a/Common/OS.cpp
+++ b/Common/OS.cpp
@@ -110,6 +110,13 @@ int GetProcessId()
 #endif
 }
 
+std::string GetHostName()
+{
+  char host[256];
+  gethostname(host, sizeof(host));
+  return std::string(host);
+}
+
 int UnlinkFile(const char *filename)
 {
 #if !defined(WIN32) || defined(__CYGWIN__)
diff --git a/Common/OS.h b/Common/OS.h
index 93cc1155aee6f1fcbc57340c9c8a6545bd403fed..d9840b3eb4905a4e9562b061885577d8cd072d2b 100644
--- a/Common/OS.h
+++ b/Common/OS.h
@@ -6,12 +6,15 @@
 #ifndef _OS_H_
 #define _OS_H_
 
+#include <string>
+
 double GetTimeInSeconds();
 void SleepInSeconds(double s);
 void GetResources(double *s, long *mem);
 void CheckResources();
 double Cpu();
 int GetProcessId();
+std::string GetHostName();
 int UnlinkFile(const char *name);
 int StatFile(const char *filename);
 int KillProcess(int pid);
diff --git a/Fltk/GmshServer.h b/Fltk/GmshServer.h
deleted file mode 100644
index 8b776c537968e80dfcab5c5fd3f4fe8a6b5fdebf..0000000000000000000000000000000000000000
--- a/Fltk/GmshServer.h
+++ /dev/null
@@ -1,274 +0,0 @@
-// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
-//
-// See the LICENSE.txt file for license information. Please report all
-// bugs and problems to <gmsh@geuz.org>.
-
-#ifndef _GMSH_SERVER_H_
-#define _GMSH_SERVER_H_
-
-int SystemCall(const char *str);
-int WaitForData(int socket, int num, double waitint);
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#if defined(_AIX)
-#include <strings.h>
-#endif
-
-#if !defined(WIN32) || defined(__CYGWIN__)
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-
-#else // pure windows
-
-#include <winsock.h>
-
-#endif
-
-static int myselect(int socket, int seconds)
-{
-  struct timeval tv;
-  tv.tv_sec = seconds;
-  tv.tv_usec = 0;
-  fd_set rfds;
-  FD_ZERO(&rfds);
-  FD_SET(socket, &rfds);
-  return select(socket + 1, &rfds, NULL, NULL, &tv);
-}
-
-class GmshServer {
- public:
-  // This should match what's in GmshClient.h (Do not use values
-  // greater that 65535: if we receive types > 65535 we assume that we
-  // receive data from a machine with a different byte ordering, and
-  // we just swap the bytes)
-  typedef enum{ CLIENT_START        = 1,
-                CLIENT_STOP         = 2,
-                CLIENT_INFO         = 10,
-                CLIENT_WARNING      = 11,
-                CLIENT_ERROR        = 12,
-                CLIENT_PROGRESS     = 13,
-                CLIENT_MERGE_FILE   = 20, // old name: CLIENT_VIEW
-                CLIENT_PARSE_STRING = 21,
-                CLIENT_OPTION_1     = 100,
-                CLIENT_OPTION_2     = 101,
-                CLIENT_OPTION_3     = 102,
-                CLIENT_OPTION_4     = 103,
-                CLIENT_OPTION_5     = 104 } MessageType;
-  static int init, s;
-
- private:
-  int _maxdelay, _portno, _sock;
-  const char *_sockname;
-  int _ReceiveData(void *buffer, int bytes)
-  {
-    char *buf = (char *)buffer;
-    int sofar = 0;
-    int remaining = bytes;
-    do {
-      int len = recv(_sock, buf + sofar, remaining, 0);
-      if(len <= 0)
-        return 0;
-      sofar += len;
-      remaining -= len;
-    } while(remaining > 0);
-    return bytes;
-  }
-  void _SwapBytes(char *array, int size, int n)
-  {
-    char *x = new char[size];
-    for(int i = 0; i < n; i++) {
-      char *a = &array[i * size];
-      memcpy(x, a, size);
-      for(int c = 0; c < size; c++)
-        a[size - 1 - c] = x[c];
-    }
-    delete [] x;
-  }
-  int _AcceptConnection(int s)
-  {
-#if defined(HAVE_NO_SOCKLEN_T)
-    int len;
-#else
-    socklen_t len;
-#endif
-    if(_portno < 0){
-#if !defined(WIN32) || defined(__CYGWIN__)
-      struct sockaddr_un from_un;
-      len = sizeof(from_un);
-      return accept(s, (struct sockaddr *)&from_un, &len);
-#else
-      return -7; // Unix sockets not available on Windows without Cygwin
-#endif
-    }
-    else{
-      struct sockaddr_in from_in;
-      len = sizeof(from_in);
-      return accept(s, (struct sockaddr *)&from_in, &len);
-    }
-  }
-
- public:
-  GmshServer(int maxdelay = 4)
-    : _maxdelay(maxdelay), _portno(-1), _sock(0), _sockname(NULL) {}
-  ~GmshServer(){}
-  int StartClient(const char *command, const char *sockname = NULL)
-  {
-    int justwait = 0;
-
-    if(!command || !strlen(command))
-      justwait = 1;
-
-    _sockname = sockname;
-
-    // no socket? launch the command directly
-    if(!_sockname) {
-      SystemCall(command);
-      return 1;
-    }
-
-    if(strstr(_sockname, "/") || strstr(_sockname, "\\") || !strstr(_sockname, ":")){
-      // UNIX socket (testing ":" is not enough with Windows paths)
-      _portno = -1;
-    }
-    else{
-      // TCP/IP socket
-      const char *port = strstr(_sockname, ":");
-      _portno = atoi(port + 1);
-    }
-    
-    if(_portno < 0){
-      // delete the file if it already exists
-#if !defined(WIN32) || defined(__CYGWIN__)
-      unlink(_sockname);
-
-      // make the socket
-      s = socket(PF_UNIX, SOCK_STREAM, 0);
-      if(s < 0)
-        return -1;  // Error: Couldn't create socket
-      
-      // bind the socket to its name
-      struct sockaddr_un addr_un;
-      memset((char *) &addr_un, 0, sizeof(addr_un));
-      strcpy(addr_un.sun_path, _sockname);
-      addr_un.sun_family = AF_UNIX;
-      if(bind(s, (struct sockaddr *)&addr_un, sizeof(addr_un)) < 0)
-        return -2;  // Error: Couldn't bind socket to name
-
-      // change permissions on the socket name in case it has to be rm'd later
-      chmod(_sockname, 0666);
-#else
-      return -7; // Unix sockets not available on Windows without Cygwin
-#endif
-    }
-    else{
-#if defined(WIN32) && !defined(__CYGWIN__)
-      if(!init){ 
-        WSADATA wsaData;
-        int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
-        if(iResult != NO_ERROR)
-          return -8;  // Error: Couldn't initialize Windows sockets
-      }
-#endif
-      if(init != _portno){ 
-        // We need a better solution to deal with addresses that have
-        // already been bound...
-        init = _portno;
-        
-        // make the socket
-        s = socket(AF_INET, SOCK_STREAM, 0);
-#if !defined(WIN32) || defined(__CYGWIN__)
-        if(s < 0)
-#else
-        if(s == INVALID_SOCKET)
-#endif
-          return -1;  // Error: Couldn't create socket
-        
-        // bind the socket to its name
-        struct sockaddr_in addr_in;
-        memset((char *) &addr_in, 0, sizeof(addr_in));
-        addr_in.sin_family = AF_INET;
-        addr_in.sin_addr.s_addr = INADDR_ANY;
-        addr_in.sin_port = htons(_portno);
-        if(bind(s, (struct sockaddr *)&addr_in, sizeof(addr_in)) < 0)
-          return -2;  // Error: Couldn't bind socket to name
-      }
-    }
-
-    if(!justwait)
-      SystemCall(command); // Start the solver
-    
-    // listen on socket (queue up to 20 connections before having
-    // them automatically rejected)
-    if(listen(s, 20))
-      return -3;  // Error: Socket listen failed
-    
-    if(justwait){
-      // wait indefinitely until we get data
-      if(WaitForData(s, -1, 0.5))
-        return -6; // not an actual error: we just stopped listening
-    }
-    else{
-      // Wait at most _maxdelay seconds for data, issue error if no
-      // connection in that amount of time
-      if(!myselect(s, _maxdelay))
-        return -4;  // Error: Socket listening timeout
-    }
-
-    // accept connection request
-    if((_sock = _AcceptConnection(s)) < 0)
-      return -5;  // Error: Socket accept failed
-    
-    return _sock;
-  }
-  int ReceiveMessageHeader(int *type, int *len)
-  {
-    bool swap = false;
-    if(_ReceiveData(type, sizeof(int))){
-      if(*type < 0) return 0;
-      if(*type > 65535){ 
-        // the data comes from a machine with different endianness and
-        // we must swap the bytes
-        swap = true;
-        _SwapBytes((char*)type, sizeof(int), 1);
-      }
-      if(_ReceiveData(len, sizeof(int))){
-        if(*len < 0) return 0;
-        if(swap) _SwapBytes((char*)len, sizeof(int), 1);
-        return 1;
-      }
-    }
-    return 0;
-  }
-  int ReceiveMessageBody(int len, char *str)
-  {
-    if(_ReceiveData(str, len) == len) {
-      str[len] = '\0';
-      return 1;
-    }
-    return 0;
-  }
-  int StopClient()
-  {
-#if !defined(WIN32) || defined(__CYGWIN__)
-    if(_portno < 0){
-      // UNIX socket
-      if(unlink(_sockname) == -1)
-        return -1;  // Impossible to unlink the socket
-    }
-    close(_sock);
-#else
-    closesocket(_sock);
-#endif
-    return 0;
-  }
-};
-
-#endif
diff --git a/Fltk/GmshSocket.h b/Fltk/GmshSocket.h
new file mode 100644
index 0000000000000000000000000000000000000000..549185a193320e34d7b47850d1444879c5265cfe
--- /dev/null
+++ b/Fltk/GmshSocket.h
@@ -0,0 +1,451 @@
+// Gmsh - Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _GMSH_SOCKET_H_
+#define _GMSH_SOCKET_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(_AIX)
+#include <strings.h>
+#endif
+
+#if !defined(WIN32) || defined(__CYGWIN__)
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#else
+#include <winsock.h>
+#include <process.h>
+#endif
+
+class GmshSocket{
+ public:
+  // types of messages that can be exchanged (never use values greater
+  // that 65535: if we receive a type > 65535 we assume that we
+  // receive data from a machine with a different byte ordering, and
+  // we swap the bytes in the payload)
+  enum MessageType{ 
+    CLIENT_START        = 1,
+    CLIENT_STOP         = 2,
+    CLIENT_INFO         = 10,
+    CLIENT_WARNING      = 11,
+    CLIENT_ERROR        = 12,
+    CLIENT_PROGRESS     = 13,
+    CLIENT_MERGE_FILE   = 20, // old name: CLIENT_VIEW
+    CLIENT_PARSE_STRING = 21,
+    CLIENT_SPEED_TEST   = 30,
+    CLIENT_OPTION_1     = 100,
+    CLIENT_OPTION_2     = 101,
+    CLIENT_OPTION_3     = 102,
+    CLIENT_OPTION_4     = 103,
+    CLIENT_OPTION_5     = 104};
+ protected:
+  // the socket descriptor
+  int _sock;
+  // the socket name
+  const char *_sockname;
+  // send some data over the socket
+  void _SendData(const void *buffer, int bytes)
+  {
+    const char *buf = (const char *)buffer;
+    int sofar = 0;
+    int remaining = bytes;
+    do {
+      ssize_t len = send(_sock, buf + sofar, remaining, 0); 
+      sofar += len;
+      remaining -= len;
+    } while(remaining > 0);
+  }
+  // receive some data over the socket
+  int _ReceiveData(void *buffer, int bytes)
+  {
+    char *buf = (char *)buffer;
+    int sofar = 0;
+    int remaining = bytes;
+    do {
+      int len = recv(_sock, buf + sofar, remaining, 0);
+      if(len <= 0)
+        return 0;
+      sofar += len;
+      remaining -= len;
+    } while(remaining > 0);
+    return bytes;
+  }
+  // utility function to swap bytes in an array
+  void _SwapBytes(char *array, int size, int n)
+  {
+    char *x = new char[size];
+    for(int i = 0; i < n; i++) {
+      char *a = &array[i * size];
+      memcpy(x, a, size);
+      for(int c = 0; c < size; c++)
+        a[size - 1 - c] = x[c];
+    }
+    delete [] x;
+  }
+  // sleep for some milliseconds
+  void _Sleep(int ms)
+  {
+#if !defined(WIN32) || defined(__CYGWIN__)
+    usleep(1000 * ms);
+#else
+    Sleep(ms);
+#endif
+  }
+ public:
+  GmshSocket() : _sock(0), _sockname(0)
+  {
+#if defined(WIN32) && !defined(__CYGWIN__)
+    static bool first = true;
+    if(first){
+      first = false;
+      WSADATA wsaData;
+      int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
+      if(iResult != NO_ERROR){
+        // Error: Couldn't initialize Windows sockets...
+      }
+    }
+#endif
+  }
+  ~GmshSocket()
+  {
+#if defined(WIN32) && !defined(__CYGWIN__)
+    WSACleanup();
+#endif
+  }
+  // utility function to wait for some data to read on a socket (if
+  // seconds==0 we check for available data and return immediately,
+  // i.e., we do polling)
+  int Select(int socket, int seconds)
+  {
+    struct timeval tv;
+    tv.tv_sec = seconds;
+    tv.tv_usec = 0;
+    fd_set rfds;
+    FD_ZERO(&rfds);
+    FD_SET(socket, &rfds);
+    // select checks all IO descriptors between 0 and its first arg,
+    // minus 1... hence the +1 below
+    return select(socket + 1, &rfds, NULL, NULL, &tv);
+  }
+  void SendString(int type, const char *str)
+  {
+    // send header (type + length)
+    _SendData(&type, sizeof(int));
+    int len = strlen(str);
+    _SendData(&len, sizeof(int));
+    // send body
+    _SendData(str, len);
+  }
+  int ReceiveHeader(int *type, int *len)
+  {
+    bool swap = false;
+    if(_ReceiveData(type, sizeof(int))){
+      if(*type < 0) return 0;
+      if(*type > 65535){ 
+        // the data comes from a machine with different endianness and
+        // we must swap the bytes
+        swap = true;
+        _SwapBytes((char*)type, sizeof(int), 1);
+      }
+      if(_ReceiveData(len, sizeof(int))){
+        if(*len < 0) return 0;
+        if(swap) _SwapBytes((char*)len, sizeof(int), 1);
+        return 1;
+      }
+    }
+    return 0;
+  }
+  int ReceiveString(int len, char *str)
+  {
+    if(_ReceiveData(str, len) == len) {
+      str[len] = '\0';
+      return 1;
+    }
+    return 0;
+  }
+};
+
+class GmshClient : public GmshSocket {
+ public:
+  GmshClient() : GmshSocket() {}
+  ~GmshClient(){}
+  int Connect(const char *sockname)
+  {
+    // slight delay to be sure that the socket is bound by the
+    // server before we attempt to connect to it...
+    _Sleep(100);
+
+    int portno;
+    char remote[256];
+    if(strstr(sockname, "/") || strstr(sockname, "\\") || !strstr(sockname, ":")){
+      // UNIX socket (testing ":" is not enough with Windows paths)
+      portno = -1;
+    }
+    else{
+      // INET socket
+      char *port = strstr(sockname, ":");
+      portno = atoi(port + 1);
+      int remotelen = strlen(sockname) - strlen(port);
+      if(remotelen > 0)
+	strncpy(remote, sockname, remotelen);
+      remote[remotelen] = '\0';
+    }
+    
+    // create socket
+    
+    if(portno < 0){
+#if !defined(WIN32) || defined(__CYGWIN__)
+      _sock = socket(PF_UNIX, SOCK_STREAM, 0);
+      if(_sock < 0)
+	return -1;  // Error: Couldn't create socket
+      // try to connect socket to given name
+      struct sockaddr_un addr_un;
+      memset((char *) &addr_un, 0, sizeof(addr_un));
+      addr_un.sun_family = AF_UNIX;
+      strcpy(addr_un.sun_path, sockname);
+      for(int tries = 0; tries < 5; tries++) {
+	if(connect(_sock, (struct sockaddr *)&addr_un, sizeof(addr_un)) >= 0)
+	  return _sock;
+	_Sleep(100);
+      }
+#else
+      // Unix sockets are not available on Windows without Cygwin
+      return -1;
+#endif
+    }
+    else{
+      _sock = socket(AF_INET, SOCK_STREAM, 0);
+      if(_sock < 0)
+	return -1; // Error: Couldn't create socket
+      struct hostent *server;
+      if(!(server = gethostbyname(remote)))
+	return -3; // Error: No such host
+      // try to connect socket to given name
+      struct sockaddr_in addr_in;
+      memset((char *) &addr_in, 0, sizeof(addr_in));
+      addr_in.sin_family = AF_INET;
+      memcpy((char *)&addr_in.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
+      addr_in.sin_port = htons(portno);
+      for(int tries = 0; tries < 5; tries++) {
+	if(connect(_sock, (struct sockaddr *)&addr_in, sizeof(addr_in)) >= 0)
+	  return _sock;
+	_Sleep(100);
+      }
+    }
+    return -2; // Error: Couldn't connect
+  }
+  void Start()
+  {
+    char tmp[256];
+#if !defined(WIN32) || defined(__CYGWIN__)
+    sprintf(tmp, "%d", getpid());
+#else
+    sprintf(tmp, "%d", _getpid());
+#endif
+    SendString(CLIENT_START, tmp);
+  }
+  void Stop()
+  {
+    SendString(CLIENT_STOP, "Goodbye!");
+  }
+  void Info(const char *str)
+  {
+    SendString(CLIENT_INFO, str);
+  }
+  void Warning(const char *str)
+  {
+    SendString(CLIENT_WARNING, str);
+  }
+  void Error(const char *str)
+  {
+    SendString(CLIENT_ERROR, str);
+  }
+  void Progress(const char *str)
+  {
+    SendString(CLIENT_PROGRESS, str);
+  }
+  void View(const char *str) 
+  {
+    // deprecated: use MergeFile(str) instead
+    SendString(CLIENT_MERGE_FILE, str);
+  }
+  void MergeFile(const char *str)
+  {
+    SendString(CLIENT_MERGE_FILE, str);
+  }
+  void ParseString(const char *str)
+  {
+    SendString(CLIENT_PARSE_STRING, str);
+  }
+  void Option(int num, const char *str)
+  {
+    if(num < 1) num = 1;
+    if(num > 5) num = 5;
+    SendString(CLIENT_OPTION_1 + num - 1, str);
+  }
+  void Disconnect()
+  {
+#if !defined(WIN32) || defined(__CYGWIN__)
+    close(_sock);
+#else
+    closesocket(_sock);
+#endif
+  }
+
+};
+
+class GmshServer : public GmshSocket{
+ private:
+  int _portno;
+ public:
+  GmshServer() : GmshSocket(), _portno(-1) {}
+  ~GmshServer(){}
+  virtual int SystemCall(const char *str) = 0;
+  virtual int WaitForData(int socket, int num, double waitint) = 0;
+  int StartClient(const char *command, const char *sockname=0, int maxdelay=4)
+  {
+    static int init = 0;
+    static int tmpsock = 0;
+
+    int justwait = (!command || !strlen(command));
+    _sockname = sockname;
+
+    // no socket? launch the command directly
+    if(!_sockname) {
+      SystemCall(command);
+      return 1;
+    }
+
+    if(strstr(_sockname, "/") || strstr(_sockname, "\\") || !strstr(_sockname, ":")){
+      // UNIX socket (testing ":" is not enough with Windows paths)
+      _portno = -1;
+    }
+    else{
+      // TCP/IP socket
+      const char *port = strstr(_sockname, ":");
+      _portno = atoi(port + 1);
+    }
+
+    if(_portno < 0){
+#if !defined(WIN32) || defined(__CYGWIN__)
+      // delete the file if it already exists
+      unlink(_sockname);
+
+      // create a socket
+      tmpsock = socket(PF_UNIX, SOCK_STREAM, 0);
+      if(tmpsock < 0)
+        return -1;  // Error: Couldn't create socket
+      
+      // bind the socket to its name
+      struct sockaddr_un addr_un;
+      memset((char *) &addr_un, 0, sizeof(addr_un));
+      strcpy(addr_un.sun_path, _sockname);
+      addr_un.sun_family = AF_UNIX;
+      if(bind(tmpsock, (struct sockaddr *)&addr_un, sizeof(addr_un)) < 0)
+        return -2;  // Error: Couldn't bind socket to name
+
+      // change permissions on the socket name in case it has to be rm'd later
+      chmod(_sockname, 0666);
+#else
+      return -7; // Unix sockets not available on Windows without Cygwin
+#endif
+    }
+    else{
+      if(init != _portno){
+        // We should be able to use setsockopt to allow reusing the
+        // same address, but I could not make it work... hence this
+        // horrible hack to avoid binding the name multiple times
+        init = _portno;
+       
+        // create a socket
+        tmpsock = socket(AF_INET, SOCK_STREAM, 0);
+#if !defined(WIN32) || defined(__CYGWIN__)
+        if(tmpsock < 0)
+#else
+        if(tmpsock == INVALID_SOCKET)
+#endif
+          return -1;  // Error: Couldn't create socket
+        
+        // bind the socket to its name
+        struct sockaddr_in addr_in;
+        memset((char *) &addr_in, 0, sizeof(addr_in));
+        addr_in.sin_family = AF_INET;
+        addr_in.sin_addr.s_addr = INADDR_ANY;
+        addr_in.sin_port = htons(_portno);
+        if(bind(tmpsock, (struct sockaddr *)&addr_in, sizeof(addr_in)) < 0)
+          return -2;  // Error: Couldn't bind socket to name
+      }
+    }
+
+    if(!justwait)
+      SystemCall(command); // Start the solver
+    
+    // listen on socket (queue up to 20 connections before having
+    // them automatically rejected)
+    if(listen(tmpsock, 20))
+      return -3;  // Error: Socket listen failed
+    
+    if(justwait){
+      // wait indefinitely until we get data
+      if(WaitForData(tmpsock, -1, 0.5))
+        return -6; // not an actual error: we just stopped listening
+    }
+    else{
+      // Wait at most maxdelay seconds for data, issue error if no
+      // connection in that amount of time
+      if(!Select(tmpsock, maxdelay))
+        return -4;  // Error: Socket listening timeout
+    }
+
+    // accept connection request
+#if defined(HAVE_NO_SOCKLEN_T)
+    int len;
+#else
+    socklen_t len;
+#endif
+    if(_portno < 0){
+#if !defined(WIN32) || defined(__CYGWIN__)
+      struct sockaddr_un from_un;
+      len = sizeof(from_un);
+      _sock = accept(tmpsock, (struct sockaddr *)&from_un, &len);
+#else
+      _sock = -7; // Unix sockets not available on Windows without Cygwin
+#endif
+    }
+    else{
+      struct sockaddr_in from_in;
+      len = sizeof(from_in);
+      _sock = accept(tmpsock, (struct sockaddr *)&from_in, &len);
+    }
+    if(_sock < 0) return -5;  // Error: Socket accept failed
+
+    return _sock;
+  }
+  int StopClient()
+  {
+#if !defined(WIN32) || defined(__CYGWIN__)
+    if(_portno < 0){
+      // UNIX socket
+      if(unlink(_sockname) == -1)
+        return -1;  // Impossible to unlink the socket
+    }
+    close(_sock);
+#else
+    closesocket(_sock);
+#endif
+    return 0;
+  }
+};  
+
+#endif
diff --git a/Fltk/Makefile b/Fltk/Makefile
index 8d0f3dc81e74dfcf80d8b3b8e1b9adcf5a3c4d91..7d13c83248e475032ed850cb08d6df894eb3496d 100644
--- a/Fltk/Makefile
+++ b/Fltk/Makefile
@@ -207,9 +207,9 @@ Colorbar_Window.o: Colorbar_Window.cpp ../Common/GmshUI.h GUI.h \
   ../Geo/SPoint3.h ../Common/Context.h ../Geo/CGNSOptions.h \
   ../Mesh/PartitionOptions.h
 Solvers.o: Solvers.cpp ../Common/Message.h ../Common/StringUtils.h \
-  Solvers.h GmshServer.h ../Common/OpenFile.h ../Common/GmshUI.h GUI.h \
+  Solvers.h GmshSocket.h ../Common/OpenFile.h ../Common/GmshUI.h GUI.h \
   Opengl_Window.h Colorbar_Window.h ../Post/ColorTable.h Popup_Button.h \
   SpherePosition_Widget.h ../Mesh/Field.h ../Post/PView.h \
   ../Geo/SPoint3.h ../Graphics/Draw.h ../Geo/SBoundingBox3d.h \
   ../Geo/SPoint3.h ../Common/Context.h ../Geo/CGNSOptions.h \
-  ../Mesh/PartitionOptions.h
+  ../Mesh/PartitionOptions.h ../Common/OS.h
diff --git a/Fltk/Solvers.cpp b/Fltk/Solvers.cpp
index 3b884081e55d19a7f47347d53f7c80bc45d72849..3a6f9b4848aca1583dd95ada3f94ba0976fddd74 100644
--- a/Fltk/Solvers.cpp
+++ b/Fltk/Solvers.cpp
@@ -8,57 +8,60 @@
 #include "Message.h"
 #include "StringUtils.h"
 #include "Solvers.h"
-#include "GmshServer.h"
+#include "GmshSocket.h"
 #include "OpenFile.h"
 #include "GmshUI.h"
 #include "GUI.h"
 #include "PView.h"
 #include "Draw.h"
 #include "Context.h"
+#include "OS.h"
 
 extern Context_T CTX;
 extern GUI *WID;
 
 SolverInfo SINFO[MAXSOLVERS];
 
-int GmshServer::init = 0;
-int GmshServer::s;
-
-// This routine polls the socket at least every 'waitint' seconds and
-// returns 0 if data is available or 1 if there was en error or if the
-// process was killed. Otherwise it just tends to current GUI events
-// (this is easier to manage than non-blocking IO, and simpler than
-// using the "real" solution, i.e., threads. Another possibility would
-// be to use Fl::add_fd())
-
-int WaitForData(int socket, int num, double waitint)
-{
-  while(1){
-    if((num >= 0 && SINFO[num].pid < 0) || (num < 0 && !CTX.solver.listen)){
-      // process has been killed or we stopped listening
-      return 1;
-    }
+class myGmshServer : public GmshServer{
+ public:
+  myGmshServer() : GmshServer() {}
+  ~myGmshServer() {}
+  int SystemCall(const char *str){ return ::SystemCall(str); }
+  int WaitForData(int socket, int num, double waitint)
+  { 
+    // This routine polls the socket at least every 'waitint' seconds and
+    // returns 0 if data is available or 1 if there was en error or if the
+    // process was killed. Otherwise it just tends to current GUI events
+    // (this is easier to manage than non-blocking IO, and simpler than
+    // using the "real" solution, i.e., threads. Another possibility would
+    // be to use Fl::add_fd())
+    while(1){
+      if((num >= 0 && SINFO[num].pid < 0) || (num < 0 && !CTX.solver.listen)){
+        // process has been killed or we stopped listening
+        return 1;
+      }
 
-    // check if there is data (call select with a zero timeout to
-    // return immediately, i.e., do polling)
-    int ret = myselect(socket, 0);
+      // check if there is data (call select with a zero timeout to
+      // return immediately, i.e., do polling)
+      int ret = Select(socket, 0);
 
-    if(ret == 0){ 
-      // nothing available: wait at most waitint seconds
-      WID->wait(waitint);
-    }
-    else if(ret > 0){ 
-      // data is there
-      return 0;
-    }
-    else{ 
-      // an error happened
-      if(num >= 0)
-        SINFO[num].pid = -1;
-      return 1;
+      if(ret == 0){ 
+        // nothing available: wait at most waitint seconds
+        WID->wait(waitint);
+      }
+      else if(ret > 0){ 
+        // data is there
+        return 0;
+      }
+      else{ 
+        // an error happened
+        if(num >= 0)
+          SINFO[num].pid = -1;
+        return 1;
+      }
     }
   }
-}
+};
 
 // This routine either launches a solver and waits for some answer (if
 // num >= 0), or simply waits for messages (if num < 0)
@@ -69,7 +72,7 @@ int Solver(int num, const char *args)
 
  new_connection:
 
-  GmshServer server(CTX.solver.max_delay);
+  GmshServer *server = new myGmshServer;
 
   if(num >= 0){
     prog = FixWindowsPath(SINFO[num].executable_name);
@@ -78,7 +81,7 @@ int Solver(int num, const char *args)
 #if !defined(WIN32)
       command += " &";
 #endif
-      server.StartClient(command.c_str());
+      server->StartClient(command.c_str(), 0, CTX.solver.max_delay);
       return 1;
     }
   }
@@ -103,6 +106,9 @@ int Solver(int num, const char *args)
   else{
     // TCP/IP socket
     sockname = CTX.solver.socket_name;
+    // if only the port is given, prepend the host name
+    if(sockname.size() && sockname[0] == ':')
+      sockname = GetHostName() + sockname;
   }
 
   if(num >= 0){
@@ -115,7 +121,7 @@ int Solver(int num, const char *args)
 #endif
   }
 
-  int sock = server.StartClient(command.c_str(), sockname.c_str());
+  int sock = server->StartClient(command.c_str(), sockname.c_str(), CTX.solver.max_delay);
 
   if(sock < 0) {
     switch (sock) {
@@ -137,7 +143,7 @@ int Solver(int num, const char *args)
       break;
     case -6:
       Msg::Info("Stopped listening for solver connections");
-      server.StopClient();
+      server->StopClient();
       break;
     case -7:
       Msg::Error("Unix sockets not available on Windows without Cygwin");
@@ -169,15 +175,16 @@ int Solver(int num, const char *args)
     if(stop || (num >= 0 && SINFO[num].pid < 0))
       break;
 
-    stop = WaitForData(sock, num, 0.1);
+    stop = server->WaitForData(sock, num, 0.1);
 
     if(stop || (num >= 0 && SINFO[num].pid < 0))
       break;
 
     int type, length;
-    if(server.ReceiveMessageHeader(&type, &length)){
+    if(server->ReceiveHeader(&type, &length)){
+      double timer = GetTimeInSeconds();
       char *message = new char[length + 1];
-      if(server.ReceiveMessageBody(length, message)){
+      if(server->ReceiveString(length, message)){
         switch (type) {
         case GmshServer::CLIENT_START:
           if(num >= 0)
@@ -236,6 +243,10 @@ int Solver(int num, const char *args)
         case GmshServer::CLIENT_ERROR:
           Msg::Direct(1, "%-8.8s: %s", num >= 0 ? SINFO[num].name : "Client", message);
           break;
+        case GmshServer::CLIENT_SPEED_TEST:
+          Msg::Info("got %d Mb message in %g seconds", strlen(message) / 1024 / 1024,
+                    GetTimeInSeconds() - timer);
+          break;
         default:
           Msg::Warning("Unknown type of message received from %s",
               num >= 0 ? SINFO[num].name : "client");
@@ -267,7 +278,7 @@ int Solver(int num, const char *args)
     }
   }
 
-  if(server.StopClient() < 0)
+  if(server->StopClient() < 0)
     Msg::Warning("Impossible to unlink the socket '%s'", sockname.c_str());
 
   if(num >= 0){
@@ -275,6 +286,7 @@ int Solver(int num, const char *args)
   }
   else{
     Msg::Info("Client disconnected: starting new connection");
+    delete server;
     goto new_connection;
   }
 
diff --git a/Mesh/Makefile b/Mesh/Makefile
index afc7c89c556620c950acb4e2ab4e1d37cff97b13..af73417385bc1dd697c36c30a69109f56b079b4c 100644
--- a/Mesh/Makefile
+++ b/Mesh/Makefile
@@ -105,7 +105,8 @@ Field.o: Field.cpp ../Common/Context.h ../Geo/CGNSOptions.h \
   ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h \
   ../Geo/GEntity.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h \
   ../Common/Message.h ../Post/OctreePost.h ../Common/Octree.h \
-  ../Common/OctreeInternals.h ../Post/PViewDataList.h ../Post/PViewData.h
+  ../Common/OctreeInternals.h ../Post/PViewDataList.h ../Post/PViewData.h \
+  ../Geo/MVertex.h ../Geo/SPoint3.h
 meshGEdge.o: meshGEdge.cpp ../Geo/GModel.h ../Geo/GVertex.h \
   ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
   ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Geo/GPoint.h \