如何在Windows中将套接字设置为阻塞模式?

3
我正在进行一些相对简单的跨平台TCP套接字编程。不幸的是,我发现当在Windows上编译时,我的套接字默认为非阻塞模式,而在OS X上则默认为阻塞模式。如何在Windows上强制将套接字设置为阻塞模式?它们通常默认为非阻塞模式吗?还是出了什么大问题?
我的代码部分基于以下简单示例: http://cs.baylor.edu/~donahoo/practical/CSockets/code/TCPEchoClient.c http://cs.baylor.edu/~donahoo/practical/CSockets/code/TCPEchoServer.c
2个回答

4
不,普通的BSD风格套接字在Windows上默认情况下不是非阻塞的。请参考Winsock Programmer's FAQ中的示例。
如果你使用MFC及其CAsyncSocket混乱代码,则是全都非阻塞的,但那是一个单独的问题

3

我相信这个参考链接可能会有所帮助;特别要注意的是:

虽然Windows Sockets支持套接字上的阻塞操作,但强烈不建议使用它们。被限制使用阻塞模式的程序员(例如作为要移植的现有应用程序的一部分)应该了解Windows Sockets中阻塞操作的语义。

如果您完全了解这里列出的无数问题,并且发现处理所有这些问题比设计您的程序以适应Windows更好,而不是从Unix进行半个端口转换,则可以使用ioctlsocket调用,将cmd参数设置为FIONBIO,第三个参数指向一个值为0的长整型。但是,请不要说您没有被警告; -)。


2
那么,Windows程序员通常会创建无限循环来不断轮询recv和其他函数吗?这似乎非常低效。 - user123003
不,异步I/O(尤其是网络)编程通常通过回调或事件完成,绝对不是轮询,正因为如此它非常高效。Winsock遵循伟大的Win API传统,因此使用消息而不是回调。或者,您可以使用http://www.sockets.com/winsock.htm#Windows_AsyncSelect而不是select,并且过上幸福快乐的生活;-)。例如,连接返回`SOCKET_ERROR`,您可以使用WSAGetLastError进行检查并获得WSAEWOULDBLOCK,然后当您使用WSAAsyncSelect关注连接时,您将在准备就绪时收到`FD_CONNECT` --等等。 - Alex Martelli
请注意,编写Winsock程序可能会让你的大脑扭曲:Python的Twisted、MFC的CAsyncSocket(http://msdn.microsoft.com/en-us/library/3tbz7kf5(VS.80).aspx)、ACE(参见http://www.artima.com/articles/io_design_patterns.html)等等都提供同样强大且更高级(易于使用;-)的异步/事件基础API,以替代Windows异步IO方法(其中许多具有跨平台优势作为额外好处;-)。 - Alex Martelli
1
抱歉,引用Windows 3.1(!)16位源代码会被扣1分。整个Windows版本系列已被Windows 95取代,而后者也已经被替换。请看顶部的日期:1993年!现在的Windows是抢占式的,这消除了主要的阻塞问题。 - MSalters
winsock标签告诉我OP想了解winsock,所以我回答了这个问题(同时建议不要编程到winsock,而是使用更高层次的抽象层,比如Twisted、MFC或ACE:当然,这些框架会使用特定系统上可用的最佳实现)。 - Alex Martelli
如果你完全了解这里列出的无数问题,并发现与其解决所有这些问题相比,将程序设计得与Windows兼容更好,那就去做吧。我喜欢它。笑死我了。 - Trevor Boyd Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接