} else {
/* Error */
printf("Error %d\n", WSAGetLastError());
}
} else {
/* Synchronous */
printf("read %ld bytes from socket\n", bytes_recvd);
}
先前工作
充分的跨越Unix和Window系统之上写代码是非常困难的, 这要求一个人去理解错综复杂的API和不同系统的非文档化细节。目前已有多个项目试图去提供一个抽象层,但是在作者的观念中,没有人能完全满意这种形式。
Marc Lehmann 的 libev 与 libeio. libev 是 UNIX I/O 多路复用的最小完美抽象。包括了一些有用的工具函数,如 ev_async,它用于异步通告,但主构件是 ev_io,用于通知用户文件描述符的状态。如前所述,一般通常不可能获得普通文件的状态变化 — 并且即使是 write(2) 和 read(2) 调用,也无法保证它们不阻塞。因此,libeio 被开发出来,用于在可管理的线程池中进行各种磁盘相关的系统调用。不幸的是,libev 做为目标的抽象层并不适合 IOCP — libev 的工作严重依赖于文件描述符,没有 socket 的概念。而且,Unix 的用户可能会将 libeio 用于文件 I/O,但移植到 Windows 上是不理想的。在 Windows 上,libev 当前使用的是 select()—每个线程不超过 64 个文件描述符。
libevent. 比 libev 更庞大,包含了 RPC,DNS,和 HTTP 代码。不支持文件 I/O。libev 在 Lehmann 评估 libevent 并加以拒绝之后开发了它 — 他的理由读起来很有趣。 关键性重写 在版本 2 完成,从而支持 Windows IOCP, 但大量的实例研究显示,它还没有正确的工作。
Boost ASIO. 它基本上满足你在 Windows 和 Unix 下使用 socket 的需要,即,Linux 的 epoll,Macintosh 的 kqueue,Windows 的 IOCP。它不支持文件 I/O。在笔者看来,对于一个并非十分复杂的问题,它过于庞大了(大约 300 个文件,大约 12000 个分号)。
命名管道例子:
常规文件在Unix文件系统中文件不能使用非阻塞I/O。有一些操作系统有异步I/O,但是它不是标准的,至少在Linux系统需要GNU libc的pthreads。为了此应用设计在不同的Unix下是方便的, 必须管理一个线程池为分配文件的I/O系统调用。
在window系统中的较好情况是真正重叠的I/O是可用的,当读或者写一个数据流到文件中。