diff --git a/iocp-links.html b/iocp-links.html index 1d62a453..cacc17cd 100644 --- a/iocp-links.html +++ b/iocp-links.html @@ -1,29 +1,201 @@
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 does have select(), it is severely
-limited: it supports only 64 file descriptors. (Does select()
-work on named pipes in windows?) Windows has the possibility of serving
-20,000 TCP connections using a different API called 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 using I/O
- completion ports. Unfortunately I/O completion ports
-
-
+ 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
Windows Sockets 2
IOCP:
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: