This document assumes you are familiar with how non-blocking socket I/O is done in UNIX.
Windows has very different notions for how asynchronous and non-blocking I/O
are done. While Windows has select() it supports only 64
file descriptors. Obviously Microsoft does understand how to make
high-concurrency servers, they've simply choosen a different paradigm for
this called overlapped
I/O. The mechanism in Windows by which multiple sockets are polled
for compltion is called
I/O
completion ports. More or less equivlant to kqueue (Macintosh,
FreeBSD, other BSDs), epoll
(Linux), event
completion ports (Solaris), poll (modern UNIXes), or select
(all operating systems). The main difference is that in UNIX you ask the
kernel to wait for file descriptors to change their readability or
writablity while in windows you wait for asynchronous functions to complete.
For example, instead of waiting for a socket to become writable and then
write(2)
to it, as you do in UNIX operating systems, you rather WSASend()
a buffer and wait for it to have been sent.
The result is that non-blocking write(2) read(2)
are non-portable to Windows. This tends to throw the poor sap assigned with
the job of porting your app to Windows into complusive nervous twitches.
Almost every socket operation that you're familar with has an overlapped counter-part (see table).
int fd; |
HANDLE handle; SOCKET socket;(the two are the same type) | |
| socket or pipe |
send(2),
write(2)
|
WSASend()
|
| socket or pipe |
recv(2),
read(2)
|
WSARecv()
|
| socket or pipe |
connect(2)
|
ConnectEx()
|
| file |
write(2)
|
WriteFileEx()
|
| file |
read(2)
|
ReadFileEx()
|
| socket and file |
sendfile() [1]
|
TransmitFile()
|
| tty |
tcsetattr(3)
|
SetConsoleMode()
|
| tty |
read(2)
|
ReadConsole()
and
ReadConsoleInput()
do not support overlapped I/O and there are no overlapped
counter-parts. One strategy to get around this is
RegisterWaitForSingleObject(&tty_wait_handle, tty_handle, tty_want_poll, NULL, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)which will execute tty_want_poll() in a different thread.
You can use this to notify the calling thread that
ReadConsoleInput() will not block.
|
| tty |
write(2)
|
WriteConsole()
is also blocking but this is probably acceptable.
|
[1] sendfile() on UNIX has not been agreed
on yet. Each operating system has a slightly different API.
tips
GetAddrInfoEx() function. It seems Asynchronous Procedure Calls must be used instead.
Windows Sockets 2
IOCP:
WSAOVERLAPPED Structure
GetOverlappedResult()
HasOverlappedIoCompleted()
CancelIoEx()
— cancels an overlapped operation.
WSASend()
WSARecv()
ConnectEx()
TransmitFile()
— an async sendfile() for windows.
WSADuplicateSocket()
— describes how to share a socket between two processes.
_setmaxstdio()
— something like setting the maximum number of file decriptors
and setrlimit(3)
AKA ulimit -n. Note the file descriptor limit on windows is
2048.
APC:
DNSQuery()
— General purpose DNS query function like res_query() on UNIX.
Pipe functions
CreateNamedPipe
CallNamedPipe
— like accept is for UNIX pipes.
ConnectNamedPipe