Jump to content

PMWSOCK.LIB

From EDM2

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:

  1. All standard BSD socket functions under their WinSock names (e.g. closesocket instead of soclose, ioctlsocket instead of ioctl).
  2. The WinSock-specific WSA* extensions, most importantly WSAAsyncSelect — 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. wVersionRequested should be MAKEWORD(1,1) for WinSock 1.1. lpWSAData is a caller-supplied WSADATA structure 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. af is AF_INET; type is SOCK_STREAM or SOCK_DGRAM. Returns a socket descriptor or INVALID_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 the SO_LINGER option.
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. backlog sets 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 via WSAAsyncSelect with the FD_CONNECT event.

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_SOCKET level: SO_REUSEADDR, SO_KEEPALIVE, SO_LINGER, SO_RCVBUF, SO_SNDBUF, SO_ERROR, SO_TYPE. At IPPROTO_TCP: TCP_NODELAY.

Multiplexed I/O

select(nfds, readfds, writefds, exceptfds, timeout)
BSD-style synchronous I/O multiplexing. Under WinSock, nfds is ignored (present only for BSD source compatibility). FD_SETSIZE is 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_NONE on 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 message wMsg to window hWnd. The message parameters carry the socket descriptor and event information:
  • mp1 — the socket descriptor
  • mp2 — 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 the WSAAsyncGet* 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, posts wMsg to hWnd. mp2 high word is the error code; if zero, buf contains a valid HOSTENT structure. Returns a task handle for use with WSACancelAsyncRequest.
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 the WSAE* prefix (e.g. WSAEWOULDBLOCK, WSAECONNREFUSED), which are numerically identical to the BSD SOCE* 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 whether fd is present in the fd_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.

See Also