diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# 0.3.0.0 - January 17th, 2021
+
+* Bump package dependencies for newer GHC/back/network.
+* Update code to work with newer dependencies.
+
 # 0.2.0.1 - November 2nd, 2016
 
 * Fix compatability with latest `data-default-class`
diff --git a/Database/Memcache/Client.hs b/Database/Memcache/Client.hs
--- a/Database/Memcache/Client.hs
+++ b/Database/Memcache/Client.hs
@@ -126,7 +126,10 @@
 
 -- | Establish a new connection to a group of Memcached servers.
 newClient :: [ServerSpec] -> Options -> IO Client
-newClient = newCluster
+newClient scs = do
+  case scs of
+    [] -> newCluster [def]
+    _  -> newCluster scs
 
 -- | Gracefully close a connection to a Memcached cluster.
 quit :: Cluster -> IO ()
diff --git a/Database/Memcache/Cluster.hs b/Database/Memcache/Cluster.hs
--- a/Database/Memcache/Cluster.hs
+++ b/Database/Memcache/Cluster.hs
@@ -42,7 +42,7 @@
 import Data.Time.Clock (NominalDiffTime)
 import Data.Time.Clock.POSIX (getPOSIXTime)
 import qualified Data.Vector as V
-import Network.Socket (HostName, PortNumber)
+import Network.Socket (HostName, ServiceName)
 import System.Timeout
 
 -- | Number of times to retry an operation before considering it failed.
@@ -53,14 +53,14 @@
         -- | Hostname of server to connect to.
         ssHost :: HostName,
         -- | Port number server is running on.
-        ssPort :: PortNumber,
+        ssPort :: ServiceName,
         -- | Authentication values to use for SASL authentication with this
         -- server.
         ssAuth :: Authentication
     } deriving (Eq, Show)
 
 instance Default ServerSpec where
-  def = ServerSpec "localhost" 11211 NoAuth
+  def = ServerSpec "127.0.0.1" "11211" NoAuth
 
 -- | Options specifies how a Memcached cluster should be configured.
 data Options = Options {
diff --git a/Database/Memcache/SASL.hs b/Database/Memcache/SASL.hs
--- a/Database/Memcache/SASL.hs
+++ b/Database/Memcache/SASL.hs
@@ -26,7 +26,6 @@
 import Control.Exception (throwIO)
 import Control.Monad
 import Data.ByteString.Char8 as B8 (ByteString, pack, singleton)
-import Data.Monoid
 
 -- | Perform SASL authentication with the server.
 authenticate :: Socket -> Authentication -> IO ()
diff --git a/Database/Memcache/Server.hs b/Database/Memcache/Server.hs
--- a/Database/Memcache/Server.hs
+++ b/Database/Memcache/Server.hs
@@ -31,8 +31,7 @@
 import Data.Time.Clock (NominalDiffTime)
 import Data.Time.Clock.POSIX (POSIXTime)
 
-import Network.BSD (getProtocolNumber, getHostByName, hostAddress)
-import Network.Socket (HostName, PortNumber(..))
+import Network.Socket (getAddrInfo, HostName, ServiceName)
 import qualified Network.Socket as S
 
 -- Connection pool constants.
@@ -52,7 +51,7 @@
         -- | Hostname of server.
         addr     :: !HostName,
         -- | Port number of server.
-        port     :: !PortNumber,
+        port     :: !ServiceName,
         -- | Credentials for server.
         auth     :: !Authentication,
         -- | When did the server fail? 0 if it is alive.
@@ -76,7 +75,7 @@
     compare x y = compare (sid x) (sid y)
 
 -- | Create a new Memcached server connection.
-newServer :: HostName -> PortNumber -> Authentication -> IO Server
+newServer :: HostName -> ServiceName -> Authentication -> IO Server
 newServer host port auth = do
     fat <- newIORef 0
     pSock <- createPool connectSocket releaseSocket
@@ -90,16 +89,18 @@
         , failed   = fat
         }
   where
-    serverHash = hash (host, fromEnum port)
+    serverHash = hash (host, port)
 
     connectSocket = do
-        proto <- getProtocolNumber "tcp"
+        let hints = S.defaultHints {
+          S.addrSocketType = S.Stream
+        }
+        addr:_ <- getAddrInfo (Just hints) (Just host) (Just port)
         bracketOnError
-            (S.socket S.AF_INET S.Stream proto)
+            (S.socket (S.addrFamily addr) (S.addrSocketType addr) (S.addrProtocol addr))
             releaseSocket
             (\s -> do
-                h <- getHostByName host
-                S.connect s (S.SockAddrInet port $ hostAddress h)
+                S.connect s $ S.addrAddress addr
                 S.setSocketOption s S.KeepAlive 1
                 S.setSocketOption s S.NoDelay 1
                 authenticate s auth
diff --git a/Database/Memcache/Socket.hs b/Database/Memcache/Socket.hs
--- a/Database/Memcache/Socket.hs
+++ b/Database/Memcache/Socket.hs
@@ -39,9 +39,8 @@
 import           Data.Binary.Get
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Lazy as L
-import           Data.Monoid
 import           Data.Word
-import           Network.Socket (Socket, isConnected, isReadable)
+import           Network.Socket (Socket)
 import qualified Network.Socket.ByteString as N
 
 -- | Send a request to the Memcached server.
@@ -66,24 +65,15 @@
     recvAll :: Int -> Builder -> IO B.ByteString
     recvAll 0 !acc = return $! toByteString acc
     recvAll !n !acc = do
-        canRead <- isSocketActive s
-        if canRead
-            then do
-                buf <- N.recv s n
-                case B.length buf of
-                    0  -> throwIO errEOF
-                    bl | bl == n ->
-                        return $! (toByteString $! acc <> fromByteString buf)
-                    bl -> recvAll (n - bl) (acc <> fromByteString buf)
-            else throwIO errEOF
+        buf <- N.recv s n
+        case B.length buf of
+            0  -> throwIO errEOF
+            bl | bl == n ->
+                return $! (toByteString $! acc <> fromByteString buf)
+            bl -> recvAll (n - bl) (acc <> fromByteString buf)
     
     errEOF :: MemcacheError
     errEOF = ProtocolError UnexpectedEOF { protocolError = "" }
-
--- | Check whether we can still operate on this socket or not.
-isSocketActive :: Socket -> IO Bool
-{-# INLINE isSocketActive #-}
-isSocketActive s = (&&) <$> isConnected s <*> isReadable s
 
 -- | Serialize a response to a ByteString Builder.
 szResponse :: Response -> Builder
diff --git a/memcache.cabal b/memcache.cabal
--- a/memcache.cabal
+++ b/memcache.cabal
@@ -1,5 +1,5 @@
 name:           memcache
-version:        0.2.0.1
+version:        0.3.0.0
 homepage:       https://github.com/dterei/memcache-hs
 bug-reports:    https://github.com/dterei/memcache-hs/issues
 synopsis:       A memcached client library.
@@ -22,7 +22,7 @@
   .
   > import qualified Database.Memcache.Client as M
   > 
-  > mc <- M.newClient [M.ServerSpec "localhost" 11211 M.NoAuth] M.def
+  > mc <- M.newClient [M.ServerSpec "localhost" "11211" M.NoAuth] M.def
   > M.set mc "key" "value" 0 0
   > v <- M.get mc "key"
   .
@@ -64,7 +64,7 @@
     bytestring         >= 0.9.2.1,
     data-default-class >= 0.1.0,
     hashable           >= 1.2.0.3,
-    network            >= 2.4,
+    network            >= 3.1.0.0,
     resource-pool      >= 0.2.1.0,
     vector             >= 0.7,
     time               >= 1.4
@@ -111,6 +111,8 @@
     bytestring    >= 0.9.2.1,
     memcache,
     network       >= 2.4
+  other-modules:
+    MockServer
   default-language: Haskell2010
   other-extensions:
     BangPatterns,
diff --git a/test/MockServer.hs b/test/MockServer.hs
new file mode 100644
--- /dev/null
+++ b/test/MockServer.hs
@@ -0,0 +1,126 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Mock Memcached server - just enough for testing client.
+module MockServer (
+        MockResponse(..), mockMCServer, withMCServer
+    ) where
+
+import qualified Database.Memcache.Client as M
+import           Database.Memcache.Socket
+import           Database.Memcache.Types
+
+import           Blaze.ByteString.Builder
+#if __GLASGOW_HASKELL__ < 710
+import           Control.Applicative
+#endif
+import           Control.Concurrent
+import           Control.Exception (bracket, handle, throwIO, SomeException)
+import           Control.Monad
+import           Data.Binary.Get
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as BC
+import qualified Data.ByteString.Lazy as L
+import           Data.IORef
+import           Data.Monoid
+import           Data.Word
+import qualified Network.Socket as N hiding (recv)
+import qualified Network.Socket.ByteString as N
+import           System.Exit
+import           System.IO
+
+import           Database.Memcache.Errors
+import           Database.Memcache.Types
+
+
+-- | Actions the mock server can take to a request.
+data MockResponse
+    = MR Response
+    | CloseConnection
+    | DelayMS Int MockResponse
+    | Noop
+
+-- | Run an IO action with a mock Memcached server running in the background,
+-- killing it once done.
+withMCServer :: Bool -> [MockResponse] -> IO () -> IO ()
+withMCServer loop res m = bracket
+    (mockMCServer loop res)
+    (\tid -> killThread tid >> threadDelay 100000)
+    (const m)
+
+-- | New mock Memcached server that responds to each request with the specified
+-- list of responses.
+mockMCServer :: Bool -> [MockResponse] -> IO ThreadId
+mockMCServer loop resp' = forkIO $ bracket 
+    (N.socket N.AF_INET N.Stream N.defaultProtocol)
+    (N.close)
+    $ \sock -> do
+        N.setSocketOption sock N.ReuseAddr 1
+        let hints = N.defaultHints {
+            N.addrFlags = [N.AI_PASSIVE]
+          , N.addrSocketType = N.Stream
+        }
+        addr:_ <- N.getAddrInfo (Just hints) Nothing (Just "11211")
+        N.bind sock $ N.addrAddress addr
+        N.listen sock 10
+        ref <- newIORef resp'
+        acceptHandler sock ref
+        when loop $ forever $ threadDelay 1000000
+  
+  where
+    acceptHandler sock ref = do
+        client <- fst <$> N.accept sock
+        resp <- readIORef ref
+        cont <- handle allErrors $ clientHandler client ref resp
+        if cont
+            then acceptHandler sock ref
+            else return ()
+
+    allErrors :: SomeException -> IO Bool
+    allErrors = const $ return True
+
+    clientHandler client ref []       = N.close client >> return False
+    clientHandler client ref (r':resp) = do
+      void $ recvReq client
+      mrHandler r'
+      where
+        mrHandler r = case r of
+            Noop            -> clientHandler client ref resp
+            (MR mr)         -> sendRes client mr >> clientHandler client ref resp
+            (DelayMS ms mr) -> do
+                writeIORef ref resp -- client may reset connection
+                threadDelay (ms * 1000)
+                mrHandler mr
+            CloseConnection -> do
+                N.close client
+                writeIORef ref resp
+                return $ not $ null resp
+
+
+
+sendRes :: N.Socket -> Response -> IO ()
+sendRes s m = N.sendAll s (toByteString $ szResponse m)
+
+recvReq :: N.Socket -> IO ()
+recvReq s = do
+    header <- recvAll s mEMCACHE_HEADER_SIZE mempty
+    let h = runGet (dzHeader PktRequest) (L.fromChunks [header])
+        bytesToRead = fromIntegral $ bodyLen h
+    when (bytesToRead > 0) $
+        void $ recvAll s bytesToRead mempty
+
+recvAll :: N.Socket -> Int -> Builder -> IO B.ByteString
+recvAll s 0 !acc = return $! toByteString acc
+recvAll s !n !acc = do
+    buf <- N.recv s n
+    case B.length buf of
+        0  -> throwIO errEOF
+        bl | bl == n ->
+            return $! (toByteString $! acc <> fromByteString buf)
+        bl -> recvAll s (n - bl) (acc <> fromByteString buf)
+  
+  where
+    errEOF :: MemcacheError
+    errEOF = ProtocolError UnexpectedEOF { protocolError = "" }
+
