diff --git a/Common/GmshDaemon.cpp b/Common/GmshDaemon.cpp
index 48c307c9abef0376c4de6bccc545e5d1753191c7..a78e6fbfdf0fb7496a482c942163113e15da711f 100644
--- a/Common/GmshDaemon.cpp
+++ b/Common/GmshDaemon.cpp
@@ -7,6 +7,8 @@
 #include "GmshMessage.h"
 #include "OS.h"
 #include "GmshSocket.h"
+#include "PView.h"
+#include "VertexArray.h"
 
 int GmshDaemon(std::string socket)
 {
@@ -42,6 +44,19 @@ int GmshDaemon(std::string socket)
               stop = true;
             }
             break;
+          case GmshSocket::GMSH_VERTEX_ARRAY:
+            {
+              // create and send a vertex array
+              if(PView::list.size()){
+                PView *view = PView::list[0];
+                view->fillVertexArrays();
+                int len;
+                char *ss = view->va_triangles->toChar(view->getNum(), len);
+                client.SendMessage(GmshSocket::GMSH_VERTEX_ARRAY, len, ss);
+                delete [] ss;
+              }
+            }
+            break;
           case GmshSocket::GMSH_SPEED_TEST:
             {
               std::string huge(500000000, 'a');
diff --git a/Common/GmshSocket.h b/Common/GmshSocket.h
index 7686c333ab65a15e2a326667dd0a049a7e0b3069..9d188b0b86318c28ce428c332c765b7cf8726d2b 100644
--- a/Common/GmshSocket.h
+++ b/Common/GmshSocket.h
@@ -48,6 +48,7 @@ class GmshSocket{
     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,
@@ -138,14 +139,17 @@ class GmshSocket{
     // minus 1... hence the +1 below
     return select(s + 1, &rfds, NULL, NULL, &tv);
   }
-  void SendString(int type, const char *str)
+  void SendMessage(int type, int length, const void *msg)
   {
     // send header (type + length)
     _SendData(&type, sizeof(int));
-    int len = strlen(str);
-    _SendData(&len, sizeof(int));
+    _SendData(&length, sizeof(int));
     // send body
-    _SendData(str, len);
+    _SendData(msg, length);
+  }
+  void SendString(int type, const char *str)
+  {
+    SendMessage(type, strlen(str), str);
   }
   void Info(const char *str){ SendString(GMSH_INFO, str); }
   void Warning(const char *str){ SendString(GMSH_WARNING, str); }
diff --git a/Common/VertexArray.cpp b/Common/VertexArray.cpp
index a2f4c1684ab15e63a7360e8492d0e74deebd07ec..c0284877f9e4532c936a36fd34d4c23920c14aa9 100644
--- a/Common/VertexArray.cpp
+++ b/Common/VertexArray.cpp
@@ -4,6 +4,7 @@
 // bugs and problems to <gmsh@geuz.org>.
 
 #include <algorithm>
+#include "GmshMessage.h"
 #include "VertexArray.h"
 #include "Context.h"
 #include "Numeric.h"
@@ -214,3 +215,63 @@ int VertexArray::getMemoryUsage()
     _colors.size() * sizeof(unsigned char);
   return bytes / 1024 / 1024;
 }
+
+char *VertexArray::toChar(int num, int &len)
+{
+  int vn = _vertices.size(), nn = _normals.size(), cn = _colors.size();
+  int vs = vn * sizeof(float), ns = nn * sizeof(char), cs = cn * sizeof(unsigned char);
+  int is = sizeof(int);
+
+  FILE *fp = fopen("toChar.txt", "w");
+  for(unsigned int i = 0; i < _vertices.size(); i++)
+    fprintf(fp, "toChar vertex %d = %f\n", i, _vertices[i]);
+  fclose(fp);
+
+  len = 5 * is + vs + ns + cs;
+  char *data = new char[len];
+  int index = 0;
+  memcpy(&data[index], &num, is); index += is;
+  memcpy(&data[index], &_numVerticesPerElement, is); index += is;
+  memcpy(&data[index], &vn, is); index += is;
+  memcpy(&data[index], &_vertices[0], vs); index + vs;
+  memcpy(&data[index], &nn, is); index += is;
+  memcpy(&data[index], &_normals[0], ns); index += ns;
+  memcpy(&data[index], &cn, is); index += is;
+  memcpy(&data[index], &_colors[0], cs); index += cs;
+  return data;
+}
+
+void VertexArray::fromChar(const char *data, bool swap)
+{
+  if(swap){
+    Msg::Error("Byte swapping not implemented in VertexArray::fromChar");
+    return;
+  }
+  int is = sizeof(int), index = 0;
+
+  int num; memcpy(&num, &data[index], is); index += is;
+  int tmp; memcpy(&tmp, &data[index], is); index += is;
+  if(tmp != _numVerticesPerElement){
+    Msg::Error("Incompatible raw data for vertex array (%d != %d)",
+               tmp, _numVerticesPerElement);
+    return;
+  }
+
+  int vn; memcpy(&vn, &data[index], is); index += is;
+  _vertices.resize(vn); int vs = vn * sizeof(float);
+  memcpy(&_vertices[0], &data[index], vs); index += vs;
+
+  int nn; memcpy(&nn, &data[index], is); index += is;
+  _normals.resize(nn); int ns = nn * sizeof(char); 
+  memcpy(&_normals[0], &data[index], ns); index += ns;
+
+  int cn; memcpy(&cn, &data[index], is); index += is;
+  _colors.resize(cn); int cs = cn * sizeof(unsigned char); 
+  memcpy(&_colors[0], &data[index], cs); index += cs;
+
+
+  FILE *fp = fopen("fromChar.txt", "w");
+  for(unsigned int i = 0; i < _vertices.size(); i++)
+    fprintf(fp, "from char vertex %d = %f\n", i, _vertices[i]);
+  fclose(fp);
+}
diff --git a/Common/VertexArray.h b/Common/VertexArray.h
index 7e05c2ce02dfb3cc11cd249cd47d627e1418f291..6c8fc165ae01c8239d1d5b1a89f5c9e3569c0d52 100644
--- a/Common/VertexArray.h
+++ b/Common/VertexArray.h
@@ -161,6 +161,10 @@ class VertexArray{
   void sort(double x, double y, double z);
   // estimate the size of the vertex array in megabytes
   int getMemoryUsage();
+  // serialize the vertex array into a string (for sending over the
+  // network)
+  char *toChar(int num, int &len);
+  void fromChar(const char *data, bool swap=false);
 };
 
 #endif
diff --git a/Fltk/menuWindow.cpp b/Fltk/menuWindow.cpp
index 9fee975112ca61fcf6437a738d122e0bd7f22bf3..a3e7908c0f847ef3d874e9a359a575182bdddc0e 100644
--- a/Fltk/menuWindow.cpp
+++ b/Fltk/menuWindow.cpp
@@ -159,7 +159,9 @@ static void file_remote_cb(Fl_Widget *w, void *data)
       GmshRemote::get(99)->name = "Remote";
       GmshRemote::get(99)->socketSwitch = "-socket %s";
       const char *exe = fl_input
-        ("Remote command:", "ssh ace25 /Users/geuzaine/src/gmsh/bin/gmsh");
+        ("Command:", 
+         //"ssh ace25 /Users/geuzaine/src/gmsh/bin/gmsh");
+         "./gmsh ../tutorial/view3.pos");
       if(exe){
         GmshRemote::get(99)->executable = exe;
         GmshRemote::get(99)->run("");
@@ -196,6 +198,16 @@ static void file_remote_cb(Fl_Widget *w, void *data)
       Msg::Error("Cannot test remote Gmsh: server not running");
     }
   }
+  else if(str == "test3"){
+    if(GmshRemote::get(99)->getServer()){
+      Msg::Info("Testing remote Gmsh server");
+      GmshRemote::get(99)->getServer()->SendString
+        (GmshSocket::GMSH_VERTEX_ARRAY, "Send me a vertex array!");
+    }
+    else{
+      Msg::Error("Cannot test remote Gmsh: server not running");
+    }
+  }
 }
 
 static void file_window_cb(Fl_Widget *w, void *data)
@@ -2209,6 +2221,7 @@ static Fl_Menu_Item bar_table[] = {
     {"Test server",  0, 0, 0, FL_SUBMENU},
       {"Send small parsed view",  0, (Fl_Callback *)file_remote_cb, (void*)"test1"},
       {"Send large dummy data",  0, (Fl_Callback *)file_remote_cb, (void*)"test2"},
+      {"Send a vertex array",  0, (Fl_Callback *)file_remote_cb, (void*)"test3"},
       {0},
     {"Stop server",  0, (Fl_Callback *)file_remote_cb, (void*)"stop", FL_MENU_DIVIDER},
 #endif
@@ -2261,6 +2274,7 @@ static Fl_Menu_Item sysbar_table[] = {
     {"Test server",  0, 0, 0, FL_SUBMENU},
       {"Send small parsed view",  0, (Fl_Callback *)file_remote_cb, (void*)"test1"},
       {"Send large dummy data",  0, (Fl_Callback *)file_remote_cb, (void*)"test2"},
+      {"Send a vertex array",  0, (Fl_Callback *)file_remote_cb, (void*)"test3"},
       {0},
     {"Stop server",  0, (Fl_Callback *)file_remote_cb, (void*)"stop", FL_MENU_DIVIDER},
 #endif
diff --git a/Fltk/solverWindow.cpp b/Fltk/solverWindow.cpp
index 6aa02706053bee078f5b66f7535014b89feb185d..d82d5e317a95cfe16f2fe324675b50a467c5288e 100644
--- a/Fltk/solverWindow.cpp
+++ b/Fltk/solverWindow.cpp
@@ -191,6 +191,9 @@ void GmshRemote::run(std::string args)
           Msg::Info("got %d Mb message in %g seconds", strlen(message) 
                     / 1024 / 1024, GetTimeInSeconds() - timer);
           break;
+        case GmshSocket::GMSH_VERTEX_ARRAY:
+          PView::fillVertexArray(length, message);
+          break;
         default:
           Msg::Warning("Unknown message type");
           Msg::Direct("%-8.8s: %s", name.c_str(), message);
diff --git a/Post/PView.h b/Post/PView.h
index b51315c8b5b4c50dec776f9a2e95cfb3aa7de8d9..d445a593eefe93f882bea721347d56af3dd33963 100644
--- a/Post/PView.h
+++ b/Post/PView.h
@@ -115,6 +115,9 @@ class PView{
   // fill the vertex arrays, given the current option and data
   void fillVertexArrays();
 
+  // fill a vertex array using a raw stream of bytes
+  static void fillVertexArray(int length, const char *data);
+
   // smoothed normals
   smooth_normals *normals;
 };
diff --git a/Post/PViewData.h b/Post/PViewData.h
index 7b28e2d2eb0d01c6849cbb7bea0eef08a5240987..a80ce3150ff93fc40e2adb76b423eafc5c3b3702 100644
--- a/Post/PViewData.h
+++ b/Post/PViewData.h
@@ -86,44 +86,44 @@ class PViewData {
   virtual int getNumPyramids(int step=-1){ return 0; }
 
   // return the number of geometrical entities in the view
-  virtual int getNumEntities(int step=-1) = 0;
+  virtual int getNumEntities(int step=-1){ return 0; }
 
   // return the number of elements in the ent-th entity, or the total
   // number of elements if ent < 0
-  virtual int getNumElements(int step=-1, int ent=-1) = 0;
+  virtual int getNumElements(int step=-1, int ent=-1){ return 0; }
 
   // return the geometrical dimension of the ele-th element in the
   // ent-th entity
-  virtual int getDimension(int step, int ent, int ele) = 0;
+  virtual int getDimension(int step, int ent, int ele){ return 0; }
 
   // return the number of nodes of the ele-th element in the ent-th
   // entity
-  virtual int getNumNodes(int step, int ent, int ele) = 0;
+  virtual int getNumNodes(int step, int ent, int ele){ return 0; }
 
   // get/set the coordinates and tag of the nod-th node from the
   // ele-th element in the ent-th entity (if the node has a tag,
   // getNode returns it)
   virtual int getNode(int step, int ent, int ele, int nod, 
-                      double &x, double &y, double &z) = 0;
+                      double &x, double &y, double &z){ return 0; }
   virtual void setNode(int step, int ent, int ele, int nod,
                        double x, double y, double z);
   virtual void tagNode(int step, int ent, int ele, int nod, int tag){}
 
   // return the number of componts available for the ele-th element in
   // the ent-th entity
-  virtual int getNumComponents(int step, int ent, int ele) = 0;
+  virtual int getNumComponents(int step, int ent, int ele){ return 0; }
 
   // return the number of values available for the ele-th element in
   // the ent-th entity
-  virtual int getNumValues(int step, int ent, int ele) = 0;
+  virtual int getNumValues(int step, int ent, int ele){ return 0; }
 
   // get the idx'th value for the ele-th element in the ent-th entity
-  virtual void getValue(int step, int ent, int ele, int idx, double &val) = 0;
+  virtual void getValue(int step, int ent, int ele, int idx, double &val){}
 
   // gets/set the comp-th component (at the step-th time step)
   // associated with the node-th node from the ele-th element in the
   // ent-th entity
-  virtual void getValue(int step, int ent, int ele, int nod, int comp, double &val) = 0;
+  virtual void getValue(int step, int ent, int ele, int nod, int comp, double &val){}
   virtual void setValue(int step, int ent, int ele, int nod, int comp, double val);
 
   // return a scalar value (same as value for scalars, norm for
@@ -133,10 +133,10 @@ class PViewData {
 
   // return the number of edges of the ele-th element in the ent-th
   // entity
-  virtual int getNumEdges(int step, int ent, int ele) = 0;
+  virtual int getNumEdges(int step, int ent, int ele){ return 0; }
 
   // return the type of the ele-th element in the ent-th entity
-  virtual int getType(int step, int ent, int ele) = 0;
+  virtual int getType(int step, int ent, int ele){ return 0; }
 
   // return the number of 2D/3D strings in the view
   virtual int getNumStrings2D(){ return 0; }
diff --git a/Post/PViewDataRemote.h b/Post/PViewDataRemote.h
new file mode 100644
index 0000000000000000000000000000000000000000..57308a8bc4fbc658b6112ce05ae9c5c118fdd737
--- /dev/null
+++ b/Post/PViewDataRemote.h
@@ -0,0 +1,37 @@
+// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle
+//
+// See the LICENSE.txt file for license information. Please report all
+// bugs and problems to <gmsh@geuz.org>.
+
+#ifndef _PVIEW_DATA_REMOTE_H_
+#define _PVIEW_DATA_REMOTE_H_
+
+#include <vector>
+#include <string>
+#include "PViewData.h"
+#include "SBoundingBox3d.h"
+
+// The container for a remote dataset (does not contain any actual
+// data!)
+class PViewDataRemote : public PViewData {
+ private: 
+  int _numTimeSteps;
+  double _min, _max;
+  std::vector<double> _timeStepMin, _timeStepMax;
+  SBoundingBox3d _bbox;
+  std::vector<double> _time;
+ public:
+  PViewDataRemote() : _numTimeSteps(1), _min(0.), _max(2.2)
+  {
+    _bbox += SPoint3(-1, -1, -1);
+    _bbox += SPoint3(1, 1, 1);
+  }
+  ~PViewDataRemote(){}
+  bool finalize(){}
+  int getNumTimeSteps(){ return _numTimeSteps; }
+  double getMin(int step=-1){ return _min; }
+  double getMax(int step=-1){ return _max; }
+  SBoundingBox3d getBoundingBox(int step=-1){ return _bbox; }
+};
+
+#endif
diff --git a/Post/PViewVertexArrays.cpp b/Post/PViewVertexArrays.cpp
index c8fc387798a203f17120a2546bf8cfc37706c842..5e342e3a36397183bab3112407649ee226aabf19 100644
--- a/Post/PViewVertexArrays.cpp
+++ b/Post/PViewVertexArrays.cpp
@@ -9,6 +9,7 @@
 #include "PView.h"
 #include "PViewOptions.h"
 #include "PViewData.h"
+#include "PViewDataRemote.h"
 #include "Numeric.h"
 #include "VertexArray.h"
 #include "SmoothData.h"
@@ -1111,3 +1112,54 @@ void PView::fillVertexArrays()
   initPView init;
   init(this);
 }
+
+void PView::fillVertexArray(int length, const char *bytes)
+{
+  int is = sizeof(int), num, numVerticesPerElement;
+
+  if(length < 2 * is){
+    Msg::Error("Too few bytes to create vertex array: %d", length);
+    return;
+  }
+  
+  memcpy(&num, &bytes[0], is);
+  memcpy(&numVerticesPerElement, &bytes[is], is);
+
+  Msg::Info("Filling vertex array (type %d) in view num %d",
+            numVerticesPerElement, num);
+
+  PView *view;
+  if(num >= 0 && num < (int)list.size()){
+    view = PView::list[num];
+  }
+  else{
+    Msg::Info("View num %d does not exist: creating new view");
+    view = new PView(new PViewDataRemote);
+  }
+
+  VertexArray *va;
+  switch(numVerticesPerElement){
+  case 1: 
+    if(view->va_points) delete view->va_points; 
+    view->va_points = new VertexArray(1, 100);
+    va = view->va_points;
+    break;
+  case 2: 
+    if(view->va_lines) delete view->va_lines; 
+    view->va_lines = new VertexArray(2, 100);
+    va = view->va_lines;
+    break;
+  case 3:
+    if(view->va_triangles) delete view->va_triangles;
+    view->va_triangles = new VertexArray(3, 100);
+    va = view->va_triangles;
+    break;
+  default: 
+    Msg::Error("Cannot fill vertex array of type %d", numVerticesPerElement);
+    return;
+  }
+
+  va->fromChar(bytes);
+  view->setChanged(false);
+  view->getData()->setDirty(false);
+}