diff --git a/Common/Context.h b/Common/Context.h
index 9a39c2b09d94611428d5f5f0d47bfc4e5c4da5d8..56497de530aa74cfef385bfe687b7d5f97d82cec 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -206,6 +206,7 @@ public :
   // solver options 
   struct{
     int max_delay, plugins ;
+    char *socket_name ;
   }solver;
 
   // print options 
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 2dbc76443f2c08a5b36ca6608b01fc290727e895..8cc6cb3e02fc18fcc0207f821d4755a42a6ee7f3 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -99,6 +99,9 @@ StringXString MeshOptions_String[] = {
 } ;
 
 StringXString SolverOptions_String[] = {
+  { F|O, "SocketName" , opt_solver_socket_name , ".gmshsock" ,
+    "Name of socket (TCP/IP if it contains the `:' character, UNIX otherwise)" },
+
   { F|O, "Name0" , opt_solver_name0 , "GetDP" ,
     "Name of solver 0" },
   { F|O, "Help0" , opt_solver_help0 , 
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 82b8317d1f80165fd4fef3daf2601575982db60d..2adab0081f3616dbdd31e37b7d07c931f50101ae 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.207 2004-11-25 02:10:30 geuzaine Exp $
+// $Id: Options.cpp,v 1.208 2004-12-06 06:54:32 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -926,6 +926,17 @@ char *opt_mesh_triangle_options(OPT_ARGS_STR){
   return CTX.mesh.triangle_options;
 }
 
+char *opt_solver_socket_name(OPT_ARGS_STR)
+{
+  if(action & GMSH_SET)
+    CTX.solver.socket_name = val;
+#if defined(HAVE_FLTK)
+  if(WID && (action & GMSH_GUI))
+    WID->solver_input[0]->value(CTX.solver.socket_name);
+#endif
+  return CTX.solver.socket_name;
+}
+
 char *opt_solver_name(OPT_ARGS_STR)
 {
 #if defined(HAVE_FLTK)
diff --git a/Common/Options.h b/Common/Options.h
index be42c9ae9ee5777a58e5c586e1e15a0564ba73c6..743cdfb2663f3e2731bba5ceb940156ced1accab 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -47,6 +47,7 @@ char * opt_general_web_browser(OPT_ARGS_STR);
 char * opt_general_scheme(OPT_ARGS_STR);
 char * opt_general_graphics_font(OPT_ARGS_STR);
 char * opt_mesh_triangle_options(OPT_ARGS_STR);
+char * opt_solver_socket_name(OPT_ARGS_STR);
 char * opt_solver_name(OPT_ARGS_STR);
 char * opt_solver_name0(OPT_ARGS_STR);
 char * opt_solver_name1(OPT_ARGS_STR);
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 99d29b07bef55ca3bf3724d647dfb9b0cfbf1115..b8f8322ec91d6b4d45c5b3656b5f76a63d8ae5e7 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.300 2004-11-25 02:10:31 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.301 2004-12-06 06:54:32 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -1087,6 +1087,8 @@ void solver_options_cb(CALLBACK_ARGS)
 void solver_options_ok_cb(CALLBACK_ARGS)
 {
   opt_solver_max_delay(0, GMSH_SET, WID->solver_value[0]->value());
+
+  opt_solver_socket_name(0, GMSH_SET, (char *)WID->solver_input[0]->value());
 }
 
 // Post options
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index f83a434ec997f89f026d104287111e61dc862f12..5f300b427220f628eb0418797b052f72d857cb16 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.385 2004-11-25 02:10:31 geuzaine Exp $
+// $Id: GUI.cpp,v 1.386 2004-12-06 06:54:32 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -2285,6 +2285,9 @@ void GUI::create_option_window()
 	solver_value[0]->maximum(10);
 	solver_value[0]->step(1);
 	solver_value[0]->align(FL_ALIGN_RIGHT);
+
+	solver_input[0] = new Fl_Input(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Socket name");
+	solver_input[0]->align(FL_ALIGN_RIGHT);
 	
 	o->end();
       }
diff --git a/Fltk/GUI.h b/Fltk/GUI.h
index 954c1e4c426bed0b55668c3574394eef5dd5f842..29b6c2f35f5fd4df184261e1555d96fa61ee7d3f 100644
--- a/Fltk/GUI.h
+++ b/Fltk/GUI.h
@@ -187,6 +187,7 @@ public:
   Fl_Group         *solver_group ;
   Fl_Check_Button  *solver_butt[20] ;
   Fl_Value_Input   *solver_value[20] ;
+  Fl_Input         *solver_input[20] ;
 
   // post-processing options
   Fl_Group         *post_group ;
diff --git a/Fltk/GmshServer.cpp b/Fltk/GmshServer.cpp
index 66b36c45cd63b8b93ba76f393a400a33cd978b3b..d7b21ad8be39e0d544139a15ce588a8aa8abbb40 100644
--- a/Fltk/GmshServer.cpp
+++ b/Fltk/GmshServer.cpp
@@ -1,4 +1,4 @@
-/* $Id: GmshServer.cpp,v 1.18 2004-10-16 22:15:17 geuzaine Exp $ */
+/* $Id: GmshServer.cpp,v 1.19 2004-12-06 06:54:32 geuzaine Exp $ */
 /*
  * Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
  *
@@ -45,6 +45,7 @@ void SystemCall(char *str);
 #include <sys/un.h>
 #include <sys/time.h>
 #include <unistd.h>
+#include <netinet/in.h>
 
 /* private functions */
 
@@ -83,16 +84,20 @@ static int Socket_UnlinkName(char *name)
 
 int Gmsh_StartClient(char *command, char *sockname)
 {
-  int s, sock;
+  static int init = 0;
+  static int s;
+  int sock;
 #if defined(linux) || defined(_AIX) || defined(__FreeBSD__)
   socklen_t len;
 #else
   int len;
 #endif
-  struct sockaddr_un addr, from;
+  struct sockaddr_un addr_un, from_un;
+  struct sockaddr_in addr_in, from_in;
   fd_set rfds;
   struct timeval tv;
-  int retval;
+  int retval, portno;
+  char *port;
 
   /* no socket? launch the command! */
   if(!sockname) {
@@ -101,23 +106,52 @@ int Gmsh_StartClient(char *command, char *sockname)
     return 1;
   }
 
-  /* first delete the socket's name if it exists */
-  Socket_UnlinkName(sockname);
+  if((port = strstr(sockname, ":"))){ /* INET socket */
+    portno = atoi(port+1);
+  }
+  else{
+    portno = -1;
+  }
+
+  if(portno < 0){ /* UNIX socket */
+    /* delete the file if it already exists */
+    Socket_UnlinkName(sockname);
 
-  /* make the socket */
-  s = socket(PF_UNIX, SOCK_STREAM, 0);
-  if(s < 0)
-    return -1;  /* Error: Couldn't create socket */
+    /* 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 */
-  strcpy(addr.sun_path, sockname);
-  addr.sun_family = AF_UNIX;
-  if(bind(s, (struct sockaddr *)&addr,
-          strlen(addr.sun_path) + sizeof(addr.sun_family)) < 0)
-    return -2;  /* Error: Couldn't bind socket to name */
+    /* bind the socket to its name */
+    strcpy(addr_un.sun_path, sockname);
+    addr_un.sun_family = AF_UNIX;
+    if(bind(s, (struct sockaddr *)&addr_un,
+	    strlen(addr_un.sun_path) + sizeof(addr_un.sun_family)) < 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);
+    /* change permissions on the socket name in case it has to be rm'd later */
+    chmod(sockname, 0666);
+  }
+  else{ /* INET socket */
+    if(init != portno){ /* FIXME: 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(s < 0)
+	return -1;  /* Error: Couldn't create socket */
+      
+      /* bind the socket to its name */
+      bzero((char *) &addr_in, 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 */
+    }
+  }
 
   /* Start the external function via system() call */
   //system(command);
@@ -127,8 +161,7 @@ int Gmsh_StartClient(char *command, char *sockname)
   if(listen(s, 20))
     return -3;  /* Error: Socket listen failed */
 
-  /* Watch s to see when it has input. */
-  /* Wait up to 4 seconds */
+  /* Watch s to see when it has input; wait up to N seconds */
   //tv.tv_sec = 4;
   tv.tv_sec = CTX.solver.max_delay;
   tv.tv_usec = 0;
@@ -139,11 +172,16 @@ int Gmsh_StartClient(char *command, char *sockname)
   if(!retval)
     return -4;  /* Error: Socket listening timeout */
 
-  len = sizeof(from);
-  if((sock = accept(s, (struct sockaddr *)&from, &len)) < 0)
-    return -5;  /* Error: Socket accept failed */
-
-  close(s);     /* don't need this socket anymore */
+  if(portno < 0){
+    len = sizeof(from_un);
+    if((sock = accept(s, (struct sockaddr *)&from_un, &len)) < 0)
+      return -5;  /* Error: Socket accept failed */
+  }
+  else{
+    len = sizeof(from_in);
+    if((sock = accept(s, (struct sockaddr *)&from_in, &len)) < 0)
+      return -5;  /* Error: Socket accept failed */
+  }
 
   return sock;
 }
@@ -164,8 +202,10 @@ int Gmsh_ReceiveString(int socket, int *type, char str[])
 
 int Gmsh_StopClient(char *sockname, int sock)
 {
-  if(Socket_UnlinkName(sockname) == -1)
-    return -1;  /* Impossible to unlink the socket */
+  if(!strstr(sockname, ":"))
+    if(Socket_UnlinkName(sockname) == -1)
+      return -1;  /* Impossible to unlink the socket */
+
   close(sock);
   return 0;
 }
diff --git a/Fltk/Solvers.cpp b/Fltk/Solvers.cpp
index 1c160fbc050ed39b8071a7ed002b8ae00e60b6de..17a9f1374dbc1bbb46c1a1f6cc23e5d1d0250665 100644
--- a/Fltk/Solvers.cpp
+++ b/Fltk/Solvers.cpp
@@ -1,4 +1,4 @@
-// $Id: Solvers.cpp,v 1.29 2004-10-25 18:48:37 geuzaine Exp $
+// $Id: Solvers.cpp,v 1.30 2004-12-06 06:54:32 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -59,9 +59,14 @@ int Solver(int num, char *args)
     return 1;
   }
 
-  sprintf(str, "%s.gmshsock-%d", CTX.home_dir, num);
-  FixWindowsPath(str, socket_name);
-  
+  if(!strstr(CTX.solver.socket_name, ":")){
+    // file socket
+    sprintf(str, "%s%s-%d", CTX.home_dir, CTX.solver.socket_name, num);
+    FixWindowsPath(str, socket_name);
+  }
+  else
+    strcpy(socket_name, CTX.solver.socket_name);
+
   sprintf(str, "\"%s\"", socket_name);
   sprintf(buffer, SINFO[num].socket_command, str);
   
diff --git a/utils/solvers/GmshClient.c b/utils/solvers/GmshClient.c
index 6f32c893a00519caa69096bc76edcc533b530487..57092b086bb0738886c0a7417c96369162fb5362 100644
--- a/utils/solvers/GmshClient.c
+++ b/utils/solvers/GmshClient.c
@@ -1,4 +1,4 @@
-/* $Id: GmshClient.c,v 1.5 2004-05-22 01:24:19 geuzaine Exp $ */
+/* $Id: GmshClient.c,v 1.6 2004-12-06 06:54:32 geuzaine Exp $ */
 /*
  * Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
  *
@@ -39,6 +39,8 @@
 #include <sys/un.h>
 #include <sys/time.h>
 #include <unistd.h>
+#include <netinet/in.h>
+#include <netdb.h>
 
 /* private functions */
 
@@ -76,27 +78,63 @@ static void Socket_Idle(double delay)
 
 int Gmsh_Connect(char *sockname)
 {
-  struct sockaddr_un addr;
+  struct sockaddr_un addr_un;
+  struct sockaddr_in addr_in;
   int len, sock;
   int tries;
+  struct hostent *server;
+  int portno, remotelen;
+  char remote[256], *port;
 
   /* slight delay to be sure that the socket is bound by the
      server before we attempt to connect to it... */
   Socket_Idle(0.1);
 
+  if((port = strstr(sockname, ":"))){
+    /* we have an INET socket */
+    portno = atoi(port+1);
+    remotelen = strlen(sockname) - strlen(port);
+    if(remotelen > 0)
+      strncpy(remote, sockname, remotelen);
+    remote[remotelen] = '\0';
+  }
+  else{
+    portno = -1;
+  }
+  
   /* create socket */
-  sock = socket(PF_UNIX, SOCK_STREAM, 0);
-  if(sock < 0)
-    return -1;  /* Error: Couldn't create socket */
 
-  /* try to connect socket to given name */
-  strcpy(addr.sun_path, sockname);
-  addr.sun_family = AF_UNIX;
-  len = strlen(addr.sun_path) + sizeof(addr.sun_family);
-  for(tries = 0; tries < 5; tries++) {
-    if(connect(sock, (struct sockaddr *)&addr, len) >= 0)
-      return sock;
-    Socket_Idle(0.1);
+  if(portno < 0){ /* UNIX socket */
+    sock = socket(PF_UNIX, SOCK_STREAM, 0);
+    if(sock < 0)
+      return -1;  /* Error: Couldn't create socket */
+    /* try to connect socket to given name */
+    strcpy(addr_un.sun_path, sockname);
+    addr_un.sun_family = AF_UNIX;
+    len = strlen(addr_un.sun_path) + sizeof(addr_un.sun_family);
+    for(tries = 0; tries < 5; tries++) {
+      if(connect(sock, (struct sockaddr *)&addr_un, len) >= 0)
+	return sock;
+      Socket_Idle(0.1);
+    }
+  }
+  else{ /* TCP/IP socket */
+    /* try to connect socket to given name */
+    sock = socket(AF_INET, SOCK_STREAM, 0);
+    if(sock < 0)
+      return -1;  /* Error: Couldn't create socket */
+    if(!(server = gethostbyname(remote)))
+      return -3; /* Error: No such host */
+    bzero((char *) &addr_in, sizeof(addr_in));
+    addr_in.sin_family = AF_INET;
+    bcopy((char *)server->h_addr, (char *)&addr_in.sin_addr.s_addr, server->h_length);
+    addr_in.sin_port = htons(portno);
+    addr_in.sin_addr.s_addr = INADDR_ANY;
+    for(tries = 0; tries < 5; tries++) {
+      if(connect(sock, (struct sockaddr *)&addr_in, sizeof(addr_in)) >= 0)
+	return sock;
+      Socket_Idle(0.1);
+    }
   }
 
   return -2;    /* Error: Couldn't connect */