Summary
- Windows Sockets 1.1 gave Windows programmers a Berkeley-style interface to TCP/IP, but it could not copy Berkeley's blocking behavior unchanged into 16-bit Windows.
- A blocked Winsock call had to keep dispatching Windows messages. That kept the cooperative desktop alive while creating strict limits on nested calls, re-entrancy and buffer ownership.
A socket call was supposed to hide the network
A socket is meant to give a program a stable way to send and receive data without making it care which network vendor supplied the underlying stack. Windows developers wanted that bargain. They also wanted a familiar starting point: Berkeley's sockets were already the standard programming model for TCP/IP on Unix.
The Windows Sockets project began at a Birds of a Feather session at Interop '91 in San Jose on 10 October 1991. The 1.1 specification records what followed: a committee, arguments by email, a draft drawing heavily on submissions from JSB and NetManage, a meeting hosted by Microsoft in December, and a working group that kept shaping the document. This was a group-built interface, not a TCP/IP protocol imposed by one vendor.
Version 1.0 was released so network-software suppliers and application developers could begin building implementations and programs against a common contract. Version 1.1, dated 20 January 1993, made clarifications and minor fixes informed by companies that had implemented version 1.0. The sequence matters: the paper was already being tested against code before the next revision settled its wording.
The specification adopted the Berkeley socket model to make Unix programmers feel at home and to simplify source-code porting. It defined the Internet protocol suite, with TCP stream sockets and UDP datagram sockets. It did not pretend that version 1.1 had standardized every possible network protocol. That was a useful boundary: application developers got a familiar interface; the document did not promise that every system underneath it would behave alike.
Then recv met a 16-bit desktop
The awkward part appears when a program waits. A blocking recv does not return until data arrives or the operation is otherwise resolved. On a pre-emptively scheduled system, the operating system can schedule other work while that process waits. Windows Sockets 1.1 could not assume that kind of scheduling on 16-bit Windows.
Microsoft's documentation describes the workaround in unusual detail. If a blocking operation could not finish immediately, the service provider started it and entered a loop: dispatch Windows messages, check whether the socket call had completed, and repeat. The loop kept the message-driven application responsive enough to continue handling its window traffic while the network read was pending.
That design did not turn a 16-bit program into a pre-emptively scheduled process. It threaded Windows message dispatch through a call that programmers might otherwise have treated as a simple wait. Messages arriving during the wait could cause the application to attempt another Winsock call. Version 1.1 forbade that nesting: a task could have only one outstanding Winsock function call. A second nested call failed with WSAEINPROGRESS.
The API supplied two small escape handles. WSAIsBlocking let an application check whether one of these calls was in progress. WSACancelBlockingCall could cancel it. More complex applications, including those with multiple document windows, could install WSASetBlockingHook and replace the default message-dispatch routine. The application gained control, along with responsibility for getting message handling right.
The interface moved work; it did not erase it
Nonblocking and asynchronous calls avoided the blocking hook's re-entrancy problem. They brought a different obligation. If an operation kept a pointer to a buffer or other memory object, the application had to keep that object valid until the operation finished. The network library could not make that lifetime decision for it.
That is the small but consequential gap between a familiar API and a portable program. Matching function names can lower the cost of starting a port. It cannot make the host's scheduling model, message loop or memory lifetime disappear. Microsoft later documented the header files supplied to ease BSD source porting, and the old Winsock.h declarations remained for compatibility with older applications after Winsock 2 introduced Winsock2.h. Compatibility itself became a piece of software that had to be carried forward.
The 1.1 specification drew its boundary at the interface and the supported TCP/IP socket types. Vendors supplied implementations; application developers chose how to wait, cancel, dispatch messages and protect memory. The shared specification made those components easier to connect. It did not make their responsibilities interchangeable.
The striking engineering choice was not that Windows copied Berkeley. It was that the working group preserved enough of Berkeley's programming vocabulary to make porting attractive, then documented where Windows could not pretend to be Unix. The message loop was the receipt: an open interface lowered one cost and showed exactly where another one landed.
Sources
Member Briefing
Deeper Profile Context
Sign in with the right membership level to unlock the full briefing and source notes.
Only for Strategic Circle
Strategic Circle
Open to all readers. Unlock profile briefings after joining and signing in.
Join Strategic CircleOnly for Leadership Alliance
Leadership Alliance
For qualified IP-asset owners and management; sign in to unlock alliance briefings.
Join Leadership Alliance





