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.