diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## Version 2.6.3.1
+
+ * Reverse breaking exception change in `Network.Socket.ByteString.recv`
+   [#215](https://github.com/haskell/network/issues/215)
+
 ## Version 2.6.3.0
 
  * New maintainers: Evan Borden (@eborden) and Kazu Yamamoto (@kazu-yamamoto).
diff --git a/Network/Socket/ByteString.hsc b/Network/Socket/ByteString.hsc
--- a/Network/Socket/ByteString.hsc
+++ b/Network/Socket/ByteString.hsc
@@ -47,9 +47,10 @@
 import Data.ByteString (ByteString)
 import Data.ByteString.Internal (createAndTrim)
 import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
+import Data.Word (Word8)
 import Foreign.Marshal.Alloc (allocaBytes)
-import Foreign.Ptr (castPtr)
-import Network.Socket (sendBuf, sendBufTo, recvBuf, recvBufFrom)
+import Foreign.Ptr (Ptr, castPtr)
+import Network.Socket (sendBuf, sendBufTo, recvBufFrom)
 
 import qualified Data.ByteString as B
 
@@ -61,14 +62,22 @@
 import Control.Monad (liftM, zipWithM_)
 import Foreign.Marshal.Array (allocaArray)
 import Foreign.Marshal.Utils (with)
-import Foreign.Ptr (Ptr, plusPtr)
+import Foreign.Ptr (plusPtr)
 import Foreign.Storable (Storable(..))
+import Foreign.C.Types (CChar, CSize(..), CInt(..))
 
 import Network.Socket.ByteString.IOVec (IOVec(..))
 import Network.Socket.ByteString.MsgHdr (MsgHdr(..))
 
+#else
+import GHC.IO.FD (FD(..), readRawBufferPtr)
 #endif
 
+#if !defined(mingw32_HOST_OS)
+foreign import CALLCONV unsafe "recv"
+  c_recv :: CInt -> Ptr CChar -> CSize -> CInt -> IO CInt
+#endif
+
 -- ----------------------------------------------------------------------------
 -- Sending
 
@@ -224,8 +233,20 @@
      -> IO ByteString  -- ^ Data received
 recv sock nbytes
     | nbytes < 0 = ioError (mkInvalidRecvArgError "Network.Socket.ByteString.recv")
-    | otherwise  = createAndTrim nbytes $ \ptr ->
-        recvBuf sock ptr nbytes
+    | otherwise  = createAndTrim nbytes $ recvInner sock nbytes
+
+recvInner :: Socket -> Int -> Ptr Word8 -> IO Int
+recvInner sock nbytes ptr =
+    fmap fromIntegral $
+#if defined(mingw32_HOST_OS)
+      throwSocketErrorIfMinus1Retry "Network.Socket.recvBuf" $
+        readRawBufferPtr "Network.Socket.ByteString.recv" (FD s 1) ptr 0 (fromIntegral nbytes)
+#else
+      throwSocketErrorWaitRead sock "recv" $
+        c_recv s (castPtr ptr) (fromIntegral nbytes) 0
+#endif
+  where
+    s = sockFd sock
 
 -- | Receive data from the socket.  The socket need not be in a
 -- connected state.  Returns @(bytes, address)@ where @bytes@ is a
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -665,7 +665,6 @@
 docdir
 oldincludedir
 includedir
-runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -737,7 +736,6 @@
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
-runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -990,15 +988,6 @@
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
-  -runstatedir | --runstatedir | --runstatedi | --runstated \
-  | --runstate | --runstat | --runsta | --runst | --runs \
-  | --run | --ru | --r)
-    ac_prev=runstatedir ;;
-  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
-  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
-  | --run=* | --ru=* | --r=*)
-    runstatedir=$ac_optarg ;;
-
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1136,7 +1125,7 @@
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir runstatedir
+		libdir localedir mandir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1289,7 +1278,6 @@
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
-  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
diff --git a/network.cabal b/network.cabal
--- a/network.cabal
+++ b/network.cabal
@@ -1,5 +1,5 @@
 name:           network
-version:        2.6.3.0
+version:        2.6.3.1
 license:        BSD3
 license-file:   LICENSE
 maintainer:     Kazu Yamamoto, Evan Borden
diff --git a/tests/Regression.hs b/tests/Regression.hs
--- a/tests/Regression.hs
+++ b/tests/Regression.hs
@@ -2,7 +2,6 @@
 module Main where
 
 import Network.Socket
-import qualified Network.Socket.ByteString as BS
 
 import Control.Exception
 
@@ -10,6 +9,8 @@
 import Test.Framework.Providers.HUnit (testCase)
 import Test.HUnit (assertFailure)
 
+import qualified Regression.Issue215 as Issue215
+
 ------------------------------------------------------------------------
 -- Tests
 
@@ -47,9 +48,10 @@
 
 tests :: [Test]
 tests =
-    [ testCase "testGetAddrInfo" testGetAddrInfo,
-      testCase "badRecvShouldThrow" badRecvShouldThrow,
-      testCase "badSendShouldThrow" badSendShouldThrow
+    [ testCase "testGetAddrInfo" testGetAddrInfo
+    , testCase "badRecvShouldThrow" badRecvShouldThrow
+    , testCase "badSendShouldThrow" badSendShouldThrow
+    , testCase "recvShouldntThrowOnClosedSocket" Issue215.main
     ]
 
 ------------------------------------------------------------------------
