CTorrent是C++实现的bt客户端,可以在各种UNIX系统上跑。2004年就停止更新了。而CTorrent-dnh作为加强版,修正了一些BUG并且增加了功能。原版结构比较简单,比较适合结合BT协议来阅读。
Windows 的API经常换,光是网络这块就已经有好几套了。而UNIX下最早的select/poll模式却一直用到了现在。虽然epoll,kqueue这些有更 好的性能,但是对于简单的BT客户端,select就够用了,至少CTorrent是这样的。Windows下也支持select模式,但是不遵守规则似 乎也是MS的惯例。下面收集了一些例证:
1)UNIX下SOCKET类型定义为int,而Windows下则是UINT_PTR。这样下面这段UNIX上正常的代码就不起作用了:
SOCKET maxfd = -1;
for (i=0; i
因为UINT_PTR是无符号的,因此-1实际上是最大值。
2)其实不用为上面的情况担心,因为Windows直接忽视select函数的第一个参数:)
3)跨平台移植代码最怕的不是缺了什么函数,而是函数相同却功能却不同。以select函数为例。
Berkeley-derived implementations (and POSIX) have the following two rules regarding select and nonblocking connects:
-
When the connection completes successfully, the descriptor becomes writable (p. 531 of TCPv2).
-
When the connection establishment encounters an error, the descriptor becomes both readable and writable (p. 530 of TCPv2).
If a socket is processing a connect call (nonblocking), failure of the connect attempt is indicated in exceptfds (application must then call getsockopt SO_ERROR to determine the error value to describe why the failure occurred).
------ MSDN
应该说Windows的这种改变并非不合理,因为在UNIX下exception fdset名不符实,用处太少,以至于经常被设为NULL而忽略。但这种既不是修BUG又不提高性能的改变却是以牺牲兼容性为代价的。
4)UNIX 下descriptor是通用概念,不仅仅是socket,因此select可以同时管理不同类型的descriptors。而Windows的 select只能接受SOCKET类型。这也是CTorrent-dnh难以移植的原因之一,它的select还管理标准输入输出。
5)UNIX的errno不是线程安全的,因此Windows使用WSAGetLastError函数代替。注意errno仍然存在,但是意义已不同了。
6)getsockopt函数的optval参数在UNIX下是int*类型,WINDOW下则是char*类型。这个比较想不通。
7)Windows下在使用网络API前后必须分别调用WSAStartup和WSACleanup函数。

No comments:
Post a Comment