diff --git a/internal/nbconn/nbconn_real_non_block_windows.go b/internal/nbconn/nbconn_real_non_block_windows.go
index b4c11555..945ec01d 100644
--- a/internal/nbconn/nbconn_real_non_block_windows.go
+++ b/internal/nbconn/nbconn_real_non_block_windows.go
@@ -8,6 +8,7 @@ import (
 	"golang.org/x/sys/windows"
 	"io"
 	"syscall"
+	"time"
 	"unsafe"
 )
 
@@ -40,6 +41,10 @@ func setSockMode(fd uintptr, mode sockMode) error {
 	return nil
 }
 
+func (c *NetConn) isDeadlineSet(dl time.Time) bool {
+	return !dl.IsZero() && dl != NonBlockingDeadline && dl != disableSetDeadlineDeadline
+}
+
 // realNonblockingWrite does a non-blocking write. readFlushLock must already be held.
 func (c *NetConn) realNonblockingWrite(b []byte) (n int, err error) {
 	if c.nonblockWriteFunc == nil {
@@ -58,6 +63,12 @@ func (c *NetConn) realNonblockingWrite(b []byte) (n int, err error) {
 	c.nonblockWriteN = 0
 	c.nonblockWriteErr = nil
 
+	if c.isDeadlineSet(c.writeDeadline) && time.Now().After(c.writeDeadline) {
+		c.nonblockWriteErr = errors.New("i/o timeout")
+
+		return 0, c.nonblockWriteErr
+	}
+
 	err = c.rawConn.Write(c.nonblockWriteFunc)
 	n = c.nonblockWriteN
 	c.nonblockWriteBuf = nil // ensure that no reference to b is kept.
@@ -98,6 +109,12 @@ func (c *NetConn) realNonblockingRead(b []byte) (n int, err error) {
 	c.nonblockReadN = 0
 	c.nonblockReadErr = nil
 
+	if c.isDeadlineSet(c.readDeadline) && time.Now().After(c.readDeadline) {
+		c.nonblockReadErr = errors.New("i/o timeout")
+
+		return 0, c.nonblockReadErr
+	}
+
 	err = c.rawConn.Read(c.nonblockReadFunc)
 	n = c.nonblockReadN
 	c.nonblockReadBuf = nil // ensure that no reference to b is kept.