PMWSOCK.LIB
PMWSOCK.LIB is an import library for PMWSOCK.DLL, the OS/2 implementation of WinSock 1.1 (Windows Sockets API). It is distributed with IBM TCP/IP for OS/2 and the IBM OS/2 Developer's Toolkit. PMWSOCK.LIB provides two things:
- All standard BSD socket functions under their WinSock names (e.g.
closesocketinstead ofsoclose,ioctlsocketinstead ofioctl). - The WinSock-specific
WSA*extensions, most importantlyWSAAsyncSelect— which integrates socket event notification with the Presentation Manager message loop.
PMWSOCK.LIB is an alternative to SO32DLL.LIB + TCP32DLL.LIB. A given application should use one set or the other, not both. Use PMWSOCK.LIB when:
- Porting a WinSock 1.1 application from Windows to OS/2.
- Writing a PM GUI application that handles network I/O through its message loop via
WSAAsyncSelect.
Use SO32DLL.LIB + TCP32DLL.LIB when writing a new OS/2-native application, a text-mode server, or code that must not depend on PM.
File size in the OS/2 Warp 4.52 Toolkit 4.5: 4,096 bytes (2000-10-16). Source DLL: PMWSOCK.DLL.
API Coverage
PMWSOCK.LIB exports 64 symbols across three groups:
| Group | Count | Description |
|---|---|---|
| BSD socket functions | ~40 | Standard socket API under WinSock names |
WSA* extensions |
~14 | WinSock lifecycle, async operations, PM integration |
| Byte-order and address utilities | ~8 | htons, htonl, inet_addr, inet_ntoa, etc.
|
WinSock Initialization
WinSock requires an explicit startup call before any socket function, analogous to sock_init() in SO32DLL.LIB.
WSAStartup(wVersionRequested, lpWSAData)- Initializes WinSock for the calling process.
wVersionRequestedshould beMAKEWORD(1,1)for WinSock 1.1.lpWSADatais a caller-suppliedWSADATAstructure filled with implementation details (version, description, max sockets, etc.). Returns 0 on success. Must be called before any other PMWSOCK function.
WSACleanup()- Releases all WinSock resources for the calling process. Call once when network activity is complete (typically at application exit). Closes any open sockets that were not explicitly closed.
Minimal initialization:
WSADATA wsa;
if (WSAStartup(MAKEWORD(1,1), &wsa) != 0) {
/* WinSock not available */
}
/* ... application code ... */
WSACleanup();
Standard Socket Functions
These are the standard BSD socket functions re-exported by PMWSOCK.DLL. Their semantics are identical to the WinSock 1.1 specification, which in turn follows BSD 4.3 with two naming differences: closesocket instead of close/soclose, and ioctlsocket instead of ioctl.
Socket lifecycle
socket(af, type, protocol)- Creates a socket.
afisAF_INET;typeisSOCK_STREAMorSOCK_DGRAM. Returns a socket descriptor orINVALID_SOCKET(−1).
closesocket(s)- Closes and releases a socket. The WinSock equivalent of
soclose(). Under WinSock, the behavior on close when data is pending is controlled by theSO_LINGERoption.
shutdown(s, how)- Partially closes a connection.
how: 0 = no more recv, 1 = no more send, 2 = both.
ioctlsocket(s, cmd, argp)- WinSock equivalent of
ioctl(). Supported commands:FIONBIO(non-blocking mode),FIONREAD(bytes available),FIOASYNC(async I/O).
Server-side
bind(s, name, namelen)- Binds a socket to a local address and port.
listen(s, backlog)- Marks a socket as passive.
backlogsets the pending connection queue depth.
accept(s, addr, addrlen)- Accepts an incoming connection, returning a new socket for it.
Client-side
connect(s, name, namelen)- Connects to a remote address. On a non-blocking socket, returns immediately with
WSAEWOULDBLOCK; completion is notified viaWSAAsyncSelectwith theFD_CONNECTevent.
Addressing
getsockname(s, name, namelen)- Returns the local address bound to a socket.
getpeername(s, name, namelen)- Returns the remote address of a connected socket.
Send and receive
send(s, buf, len, flags)/recv(s, buf, len, flags)- Send and receive on a connected socket.
sendto(s, buf, len, flags, to, tolen)/recvfrom(s, buf, len, flags, from, fromlen)- Datagram send and receive with explicit addresses.
Options
getsockopt(s, level, optname, optval, optlen)/setsockopt(s, level, optname, optval, optlen)- Query and set socket options. Supported at
SOL_SOCKETlevel:SO_REUSEADDR,SO_KEEPALIVE,SO_LINGER,SO_RCVBUF,SO_SNDBUF,SO_ERROR,SO_TYPE. AtIPPROTO_TCP:TCP_NODELAY.
Multiplexed I/O
select(nfds, readfds, writefds, exceptfds, timeout)- BSD-style synchronous I/O multiplexing. Under WinSock,
nfdsis ignored (present only for BSD source compatibility).FD_SETSIZEis 64.
Byte-Order and Address Utilities
htons(x)/ntohs(x)- 16-bit host-to-network and network-to-host byte swap.
htonl(x)/ntohl(x)- 32-bit host-to-network and network-to-host byte swap.
inet_addr(cp)- Converts a dotted-decimal string to a 32-bit network-byte-order address. Returns
INADDR_NONEon error.
inet_ntoa(in)- Converts a 32-bit address to a dotted-decimal string. Returns a pointer to a static buffer (not thread-safe).
Name Resolution
PMWSOCK.DLL provides synchronous name resolution functions equivalent to those in TCP32DLL.LIB. The async variants (below) are the preferred interface in PM applications.
gethostbyname(name)/gethostbyaddr(addr, len, type)/gethostname(name, namelen)- Host lookups. These block the calling thread during DNS resolution.
getservbyname(name, proto)/getservbyport(port, proto)- Service lookups.
getprotobyname(name)/getprotobynumber(proto)- Protocol lookups.
WSA* Extensions
PM-Integrated Async Socket Events
The key feature distinguishing PMWSOCK from the native SO32DLL API is WSAAsyncSelect. It replaces the blocking select() polling model with PM message delivery, allowing a single-threaded PM application to handle multiple sockets within its existing WinGetMsg/WinDispatchMsg loop.
WSAAsyncSelect(s, hWnd, wMsg, lEvent)- Registers a socket for asynchronous event notification. When any of the requested events occur on
s, PMWSOCK posts the messagewMsgto windowhWnd. The message parameters carry the socket descriptor and event information:mp1— the socket descriptormp2— low word: the event flag that fired; high word: error code (0 if no error)
The lEvent bitmask is a combination of:
| Flag | Value | Fires when |
|---|---|---|
FD_READ |
0x01 | Data is available to receive |
FD_WRITE |
0x02 | Send buffer has space (socket is writable) |
FD_OOB |
0x04 | Out-of-band data has arrived |
FD_ACCEPT |
0x08 | Incoming connection pending on a listening socket |
FD_CONNECT |
0x10 | Non-blocking connect() completed (success or failure)
|
FD_CLOSE |
0x20 | Connection closed by remote end |
Setting lEvent = 0 cancels all notifications for the socket (equivalent to calling WSACancelAsyncRequest). Calling WSAAsyncSelect on a socket automatically puts it in non-blocking mode.
Example: a PM server that accepts connections and receives data without a background thread:
#define WM_SOCKET (WM_USER + 1)
/* In window creation: */
sock_listen = socket(AF_INET, SOCK_STREAM, 0);
bind(sock_listen, ...);
listen(sock_listen, 5);
WSAAsyncSelect(sock_listen, hwnd, WM_SOCKET, FD_ACCEPT);
/* In WndProc: */
case WM_SOCKET:
{
int sock = SHORT1FROMMP(mp1);
int event = SHORT1FROMMP(mp2);
int err = SHORT2FROMMP(mp2);
if (err) { /* handle error */ break; }
if (event & FD_ACCEPT) {
int cs = accept(sock, NULL, NULL);
WSAAsyncSelect(cs, hwnd, WM_SOCKET, FD_READ | FD_CLOSE);
}
if (event & FD_READ) {
char buf[1024];
int n = recv(sock, buf, sizeof(buf), 0);
/* process n bytes */
}
if (event & FD_CLOSE) {
closesocket(sock);
}
}
After calling recv() or send() inside a WM_SOCKET handler, WinSock re-arms the notification automatically if more data is available. There is no need to re-register with WSAAsyncSelect after each event.
WSACancelAsyncRequest(hAsyncTaskHandle)- Cancels a pending
WSAAsyncGet*operation (see below). The task handle is the return value of theWSAAsyncGet*call.
Asynchronous Name Resolution
These functions perform DNS and service lookups without blocking, posting a PM message when the result is ready. They are the PM-native alternative to calling gethostbyname() on a background thread.
WSAAsyncGetHostByName(hWnd, wMsg, name, buf, buflen)- Starts an async DNS lookup for
name. When complete, postswMsgtohWnd.mp2high word is the error code; if zero,bufcontains a validHOSTENTstructure. Returns a task handle for use withWSACancelAsyncRequest.
WSAAsyncGetHostByAddr(hWnd, wMsg, addr, len, type, buf, buflen)- Async reverse DNS lookup (address → hostname).
WSAAsyncGetServByName(hWnd, wMsg, name, proto, buf, buflen)- Async service lookup by name.
WSAAsyncGetServByPort(hWnd, wMsg, port, proto, buf, buflen)- Async service lookup by port number.
WSAAsyncGetProtoByName(hWnd, wMsg, name, buf, buflen)- Async protocol lookup by name.
WSAAsyncGetProtoByNumber(hWnd, wMsg, number, buf, buflen)- Async protocol lookup by number.
All WSAAsyncGet* calls return immediately. The result is delivered as a PM message, keeping the UI responsive during potentially slow DNS lookups.
Error Handling
WSAGetLastError()- Returns the last WinSock error code for the calling thread. Analogous to
sock_errno()in SO32DLL. Error codes use theWSAE*prefix (e.g.WSAEWOULDBLOCK,WSAECONNREFUSED), which are numerically identical to the BSDSOCE*codes offset by 10000.
WSASetLastError(iError)- Sets the WinSock error code for the calling thread.
Blocking Hook
WinSock 1.1 has a concept of a "blocking hook" — a callback function that runs during blocking socket calls, allowing a message pump to keep the UI responsive while a call like connect() blocks. This mechanism predates non-blocking sockets and is largely superseded by WSAAsyncSelect.
WSASetBlockingHook(lpBlockFunc)- Installs a function to be called periodically during blocking WinSock calls. The hook should call
WSACancelBlockingCall()when it wants to abort the call.
WSAUnhookBlockingHook()- Restores the default blocking behavior.
WSACancelBlockingCall()- Cancels the currently executing blocking WinSock call (from within the blocking hook or from another thread). The blocking call returns with
WSAEINTR.
WSAIsBlocking()- Returns TRUE if the calling thread is currently inside a blocking WinSock call.
Internal
__WSAFDIsSet(fd, set)- The underlying function behind the
FD_ISSET(fd, set)macro. Checks whetherfdis present in thefd_set. Not called directly by applications.
Comparison with SO32DLL.LIB
| Feature | PMWSOCK.LIB | SO32DLL.LIB + TCP32DLL.LIB |
|---|---|---|
| API standard | WinSock 1.1 | BSD 4.3 / OS/2 native |
| Init call | WSAStartup() |
sock_init()
|
| Close call | closesocket(s) |
soclose(s)
|
| I/O control | ioctlsocket(s, cmd, argp) |
ioctl(s, cmd, arg)
|
| Error code | WSAGetLastError() → WSAE* |
sock_errno() → SOCE*
|
| PM async events | WSAAsyncSelect() → WM message |
Not available |
| Async DNS | WSAAsyncGetHostByName() etc. |
None (use a background thread) |
| Windows portability | Drop-in for WinSock 1.1 code | Requires porting |
| Scatter/gather | Not available | readv/writev, sendmsg/recvmsg
|
| Thread-safe DNS | Via WSAAsyncGet* |
gethostbyname_r / gethostbyaddr_r
|
| Source DLL | PMWSOCK.DLL | SO32DLL.DLL + TCP32DLL.DLL |
Usage
PMWSOCK.LIB replaces both SO32DLL.LIB and TCP32DLL.LIB. Do not link all three together.
IBM VisualAge C++ / ILINK
icc -O2 -Gm -c myapp.c ilink /PM:PM myapp.obj os2386.lib pmwsock.lib
OpenWatcom (wlink)
wcl386 -bt=os2 -mf -c myapp.c wlink system os2_pm file myapp.obj library os2386.lib library pmwsock.lib
EMX/GCC
gcc -Zomf -c myapp.c gcc -Zomf -o myapp.exe myapp.o os2386.lib pmwsock.lib
Include files
The WinSock headers are part of the IBM TCP/IP SDK:
| Header | Contents |
|---|---|
winsock.h |
Master WinSock 1.1 header: all socket types, WSADATA, WSAEVENT, function prototypes, WSAE* error codes, FD_* event flags. Includes sys\socket.h, netdb.h, utils.h as appropriate.
|
sys\socket.h |
struct sockaddr, AF_*, SOCK_*, SOL_SOCKET, SO_*
|
netinet\in.h |
struct in_addr, IPPROTO_*, INADDR_ANY, INADDR_NONE
|
netdb.h |
HOSTENT, SERVENT, PROTOENT, synchronous lookup prototypes
|
For most WinSock applications, including winsock.h alone is sufficient.
Version History
| Version | IBM TCP/IP release | Date | Notes |
|---|---|---|---|
| 1.0 | IBM TCP/IP for OS/2 3.0 (Warp 3) | 1994 | Initial release. WinSock 1.1 compliance: standard socket functions, WSAStartup/WSACleanup, WSAAsyncSelect.
|
| 1.1 | IBM TCP/IP for OS/2 4.1 (Warp 4) | 1996 | Added all WSAAsyncGet* functions. Improved PM message delivery reliability.
|
| 1.1 | IBM TCP/IP for OS/2 4.21 / OS/2 Warp 4.52 | 2000 | Final IBM release. File size: 4,096 bytes (2000-10-16). |
Note: PMWSOCK implements WinSock 1.1. WinSock 2 (with overlapped I/O, protocol-independent name resolution, WSASocket, WSARecv/WSASend, etc.) was never implemented for OS/2.