diff --git a/.gitignore b/.gitignore
index 5093ef3..23e2fdd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@ doc/*.7
 doc/*.html
 doc/*.xml
 src/libzmq.pc
+bin/
 lib/
 builds/msvc/*.suo
 builds/msvc/*/*.user
diff --git a/doc/zmq_getsockopt.txt b/doc/zmq_getsockopt.txt
index a2677c7..c034ef9 100644
--- a/doc/zmq_getsockopt.txt
+++ b/doc/zmq_getsockopt.txt
@@ -26,6 +26,19 @@ value stored in the buffer.
 The following options can be retrieved with the _zmq_getsockopt()_ function:
 
 
+ZMQ_TYPE: Retrieve socket type.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The 'ZMQ_TYPE option shall retrieve the socket type for the specified
+'socket'.  The socket type is specified at socket creation time and
+cannot be modified after creation.
+
+[horizontal]
+Option value type:: uint64_t
+Option value unit:: N/A
+Default value:: N/A
+Applicable socket types:: all
+
+
 ZMQ_RCVMORE: More message parts to follow
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 The 'ZMQ_RCVMORE' option shall return a boolean value indicating if the
diff --git a/include/zmq.h b/include/zmq.h
index c5f79d4..b8ab6d4 100644
--- a/include/zmq.h
+++ b/include/zmq.h
@@ -179,6 +179,7 @@ ZMQ_EXPORT int zmq_term (void *context);
 #define ZMQ_RCVMORE 13
 #define ZMQ_FD 14
 #define ZMQ_EVENTS 15
+#define ZMQ_TYPE 16
 
 /*  Send/recv options.                                                        */
 #define ZMQ_NOBLOCK 1
diff --git a/src/options.cpp b/src/options.cpp
index dcbb51d..0bef93f 100644
--- a/src/options.cpp
+++ b/src/options.cpp
@@ -25,6 +25,7 @@
 #include "err.hpp"
 
 zmq::options_t::options_t () :
+    socket_type (-1),
     hwm (0),
     swap (0),
     affinity (0),
@@ -137,6 +138,15 @@ int zmq::options_t::getsockopt (int option_, void *optval_, size_t *optvallen_)
 {
     switch (option_) {
 
+    case ZMQ_TYPE:
+        if (*optvallen_ < sizeof (int64_t)) {
+            errno = EINVAL;
+            return -1;
+        }
+        *((int64_t*) optval_) = socket_type;
+        *optvallen_ = sizeof (int64_t);
+        return 0;
+
     case ZMQ_HWM:
         if (*optvallen_ < sizeof (uint64_t)) {
             errno = EINVAL;
diff --git a/src/options.hpp b/src/options.hpp
index 908b166..e466485 100644
--- a/src/options.hpp
+++ b/src/options.hpp
@@ -51,6 +51,9 @@ namespace zmq
         uint64_t sndbuf;
         uint64_t rcvbuf;
 
+        //  Socket type.
+        int64_t socket_type;
+
         //  These options are never set by the user directly. Instead they are
         //  provided by the specific socket type.
         bool requires_in;
diff --git a/src/pair.cpp b/src/pair.cpp
index faea167..9ba0119 100644
--- a/src/pair.cpp
+++ b/src/pair.cpp
@@ -31,6 +31,7 @@ zmq::pair_t::pair_t (class ctx_t *parent_, uint32_t slot_) :
     outpipe_alive (false),
     terminating (false)
 {
+    options.socket_type = ZMQ_PAIR;
     options.requires_in = true;
     options.requires_out = true;
 }
diff --git a/src/pub.cpp b/src/pub.cpp
index 6edd991..af8dd4a 100644
--- a/src/pub.cpp
+++ b/src/pub.cpp
@@ -29,6 +29,7 @@ zmq::pub_t::pub_t (class ctx_t *parent_, uint32_t slot_) :
     active (0),
     terminating (false)
 {
+    options.socket_type = ZMQ_PUB;
     options.requires_in = false;
     options.requires_out = true;
 }
diff --git a/src/pull.cpp b/src/pull.cpp
index cbfcdbf..476efcf 100644
--- a/src/pull.cpp
+++ b/src/pull.cpp
@@ -26,6 +26,7 @@ zmq::pull_t::pull_t (class ctx_t *parent_, uint32_t slot_) :
     socket_base_t (parent_, slot_),
     fq (this)
 {
+    options.socket_type = ZMQ_PULL;
     options.requires_in = true;
     options.requires_out = false;
 }
diff --git a/src/push.cpp b/src/push.cpp
index 20943fc..b936172 100644
--- a/src/push.cpp
+++ b/src/push.cpp
@@ -27,6 +27,7 @@ zmq::push_t::push_t (class ctx_t *parent_, uint32_t slot_) :
     socket_base_t (parent_, slot_),
     lb (this)
 {
+    options.socket_type = ZMQ_PUSH;
     options.requires_in = false;
     options.requires_out = true;
 }
diff --git a/src/rep.cpp b/src/rep.cpp
index b2ada66..0039083 100644
--- a/src/rep.cpp
+++ b/src/rep.cpp
@@ -27,6 +27,7 @@ zmq::rep_t::rep_t (class ctx_t *parent_, uint32_t slot_) :
     sending_reply (false),
     request_begins (true)
 {
+    options.socket_type = ZMQ_REP;
 }
 
 zmq::rep_t::~rep_t ()
diff --git a/src/req.cpp b/src/req.cpp
index 8a5126d..3e2670b 100644
--- a/src/req.cpp
+++ b/src/req.cpp
@@ -27,6 +27,7 @@ zmq::req_t::req_t (class ctx_t *parent_, uint32_t slot_) :
     receiving_reply (false),
     message_begins (true)
 {
+    options.socket_type = ZMQ_REQ;
 }
 
 zmq::req_t::~req_t ()
diff --git a/src/sub.cpp b/src/sub.cpp
index bee8a06..3e462fb 100644
--- a/src/sub.cpp
+++ b/src/sub.cpp
@@ -30,6 +30,7 @@ zmq::sub_t::sub_t (class ctx_t *parent_, uint32_t slot_) :
     has_message (false),
     more (false)
 {
+    options.socket_type = ZMQ_SUB;
     options.requires_in = true;
     options.requires_out = false;
     zmq_msg_init (&message);
diff --git a/src/xrep.cpp b/src/xrep.cpp
index c1cfb00..8b9e556 100644
--- a/src/xrep.cpp
+++ b/src/xrep.cpp
@@ -32,6 +32,7 @@ zmq::xrep_t::xrep_t (class ctx_t *parent_, uint32_t slot_) :
     more_out (false),
     terminating (false)
 {
+    options.socket_type = ZMQ_XREP;
     options.requires_in = true;
     options.requires_out = true;
 
diff --git a/src/xreq.cpp b/src/xreq.cpp
index 2373f34..e5699b9 100644
--- a/src/xreq.cpp
+++ b/src/xreq.cpp
@@ -27,6 +27,7 @@ zmq::xreq_t::xreq_t (class ctx_t *parent_, uint32_t slot_) :
     fq (this),
     lb (this)
 {
+    options.socket_type = ZMQ_XREQ;
     options.requires_in = true;
     options.requires_out = true;
 }
