IOCPSOCK version 3.0


The IOCPSOCK extension contains two (2) commands provided to the interpreter:
socket2
Has the exact syntax as the core's socket command, but operates under a different I/O model. An IPv6 address can be used. The different fconfigure options are as follows:

-backlog
Sets (or gets) the pool count of AcceptEx calls on the listening socket. Keep raising this if you are prone to many "peer disconnected" errors when starting to read from a new connection or when clients trying to connect are getting "connection refused" or "timeout" errors. The sky is the limit on this setting. The only limit to be concerned about is available memory. The calculation is ~500 bytes * the backlog size of the non-paged pool will be reserved (ie. ~0.5 * 200 == ~100K of the non-paged pool). The non-paged pool is a global resource and is limited to about 1/4 of the physical memory.
-sendcap
Sets (or gets) the sending limit in terms of the count of concurrent WSASend operations allowed. Think of this as a poor-man's throttle. More means speedier, but the per socket resource limit is raised. Use "1" for lowest resource usage (HTTPD) and about "25" or greater for highest performance (FTPD). This option can be set for listening sockets and will be inherited to new connections.
-recvmode
Sets (or gets) the receive mode and properties of the mode. Choices are "zero-byte", "flow-controlled" or "burst-detection <cap>". This option can be set for listening sockets and will be inherited to new connections.

zero-byte is the lowest in terms of resource usage per socket and is the default, but is not the speediest. What's going on under-the-hood is a zero-byte receive buffer is used for the overlapped WSARecv call so it is only used as an alert for when the socket becomes readable. When the call to read the socket comes in to the Tcl_DriverInputProc, a non-blocking, non-overlapped WSARecv call is made using the actual channel buffer as the write space. This mode is best used with applications that have a high concurrent socket count (possibly over 50K), move small amounts of data and that will have a long life span. HTTPD is a good example where this mode would be helpful.

flow-controlled is the "normal" mode that should be used for fast transfers. Under-the-hood, this is "by-the-book" overlapped-I/O. To start the socket "listening" for receives, WSARecv is called for overlapped operation with a pre-allocated buffer that is handed to the kernel. For when the Tcl_DriverInputProc is called, the buffer is memcpy'd into the channel buffer, and a new overlapped WSARecv call is made with a new kernel buffer (same size as the channel buffer) to take the last ones place.

burst-detection mode allows for additional reads behind the scenes and will increase the concurrent pool of outstanding WSARecv calls within the limits specified. <cap> is the pool size limit. Overlapped-I/O has the ability to post numerous outstanding WSARecv calls to match the (instantanious) incoming load. This mode should only be used for problematic networks that are "bursty" with regards to data flow. One should not use this mode if resource usage is at a premium. The pool count does not reduce once increased by load detection. flow-controlled is the better option until you know you can improve transfer performance with burst-detection.

iocp_stats
returns useful info about what's going on under the hood.
The IOCPSOCK extension also exports the following C functions through its own Stubs file (iocpstubXX.lib). Like other Tcl extensions, #include "iocpsock.h" from your code and set -D USE_IOCP_STUBS in the compile. Use a block like the following in your shell's Init() function:
#ifdef STATIC_BUILD
    Tcl_StaticPackage(interp, "Iocpsock", Iocpsock_Init, Iocpsock_SafeInit);
    if (Iocpsock_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
#else
    if (Iocpsock_InitStubs(interp, "3.0", 0 /*exact*/) == TCL_ERROR) {
	return TCL_ERROR;
    }
#endif
int Iocpsock_Init (Tcl_Interp *interp)
Initializes the extension for use in the current interpreter.

int Iocpsock_SafeInit (Tcl_Interp *interp)
Same as Iocpsock_Init as the use of sockets are not considered unsafe.

Tcl_Channel Iocp_OpenTcpClient (Tcl_Interp *interp, CONST char *port, CONST char *host, CONST char *myaddr, CONST char *myport, int async)
Same as the core's Tcl_OpenTcpClient, but the port and myport arguments are a CONST char * not an int to support service names to getaddrinfo().

Tcl_Channel Iocp_OpenTcpServer (Tcl_Interp *interp, CONST char *port, CONST char *host, Tcl_TcpAcceptProc *acceptProc, ClientData acceptProcData)
Same as the core's Tcl_OpenTcpServer, but the port argument is a CONST char * not an int to support service names to getaddrinfo().

Tcl_Channel Iocp_MakeTcpClientChannel (ClientData sock)
Just like the core's Tcl_MakeTcpClientChannel, but can fail and return a NULL Tcl_Channel. When it does fail, check for the error with GetLastError(). You may use the exported Tcl_Win32Err* helper functions if you like. IPv4 or IPv6 sockets are allowed.

CONST char *Tcl_WinErrId (void)
Tcl_WinErrId returns a machine-readable textual identifier such as "ERROR_DEVICE_DOOR_OPEN" that corresponds to the current return of Win32's GetLastError(). Same as the core's Tcl_ErrnoId(), but for the WINDOWS class of errors.

CONST char *Tcl_WinErrMsg (void)
Tcl_WinErrMsg returns a human-readable string such as "permission denied" that corresponds to the current return of Win32's GetLastError(). The strings returned by these functions are statically allocated and the caller must not free or modify them. Same as the core's Tcl_ErrnoMsg, but for the WINDOWS class of errors.

CONST char *Tcl_WinError (Tcl_Interp *interp)
Tcl_WinError returns a human-readable diagnostic message for the error (this is the same value that will appear as the fourth element in the -errorcode value). It may be convenient to include this string as part of the error message returned to the application in the interpreter's result. Same as the core's Tcl_PosixError, but for the WINDOWS class of errors.