当前位置:C++技术网 > 资讯 > [C++] Windows Socket IO 完成端口的实现是如何实现的

[C++] Windows Socket IO 完成端口的实现是如何实现的

更新时间:2016-08-22 19:46:35浏览次数:1+次

在如今的网络下,大多数软件都是靠Socket库的接口来进行通信,里面包含了 阻塞 和 非阻塞 两种模式,也就是 同步 与 异步。

起初网络编程时,我选择使用同步,因为同步比较简单,用起来也很方便;但这也是在我使用 Win32 控制台编程的环境下,且不知道异步的使用方法条件下。

后来接触到了 MFC,发现使用同步会对窗口造成假死状态。

于是查了很多网页,看了一些网络视频,兜了很多的圈,终于知道了原因;因为窗口界面是 MFC 用 WinMain() 来进行一个复杂的运算绘画出来的,所有的窗口操作都是靠主线程来完成的,也理解到了为什么 MFC 比 C/C++ 慢的原因。

之后我就想了一个解决方法,那就是线程。

解决步骤:

1) 主窗口负责初始化

2) 创建一条线程负责接待客户。

3) 如有客户连接创建一条线程负责接受客户的请求,并处理客户的请求。

但是这样就会造成很大的问题,问题分别如下:

1) 线程创建有失败的时候。

2) 关闭是个问题。如果想关闭,就必须设置逻辑锁,非常的复杂。

3) 多线程不但对 CPU 造成很大的压力。为什么多线程会对 CPU 造成很大的压力?后来我又是去百度了一段时间。因为多线程在一个 CPU 的情况下,并不是真正意义上的多线程。

我用张图说明:

就如图所示,CPU 就像一个动力齿轮一样,一定的频率转动着,CPU 转到哪条线程就发出信号处理去处理里面的事件,让人看上去感觉是并发了。

最后我为了解决多线程的不利,就采用了窗口的消息机制。解决方案变成了如下:

1) 主窗口负责初始化

2) 创建一条线程负责接待客户。

3) 如有客户连接发送自定义消息到窗口,让主线程来处理客户的请求。

于是问题接着一个又一个的来了,这样虽然是对CPU负担减少了,但是接待客户的线程还是没法关闭,因为 accept() 是阻塞的,就算我设置了逻辑锁,也没有办法循环判断。

于是我又去找了百度,答案也只有 异步 或 更为方便的 CSocket 类。

异步的方法就是使用 WSAAsyncSelect() 把套接字设置成异步,发送消息到指定窗口来解决,这个方法和我上面差不多,但是这个方法可以随时关闭,不需要逻辑锁,明显是方便了,但是问题又接着来了,WSA有一套扩展函数,不知是什么时候开发出来,让我非常担心通用性,而且也只能用在有窗口的情况下使用,没有窗口时怎么办呢?

CSocket 的方法我大致的调试跟踪过,发现它的处理方式好像是,在内部创建一个空白窗口来处理消息,用的版本也是1.1的,但是逻辑太过复杂,而且也只能兼容 MFC 的,那么效率又是一个问题了。

最后我查了很多方法,发现了 Windows Socket IO 完成端口可以算是效率最高的,通用性也应该不错,但是网络上查出来的只是相关的函数名称 和 部分代码的编写,但是我不太理解完成端口的原理,所以写不出来完成端口的服务器和客户端类,特地求助于C++技术网。如果这牵扯的知识太过多的话,希望作者可以允许QQ聊天理解相关性。

曾经老师和我说过,遇到问题,请勿先求人,自己来解决,如果实在不能解决再求人。我现在就遇到了不能再理解的情况,我先感谢C++技术网的作者的说明。


C++技术网解答:

    很认真的看了你的所有描述,非常的佩服,非常的独立带有自己的思考用于实践的去探索和解决自己的问题,这种精神是研究技术的不可多得的精神。我很欣赏。而且,通过一路的研究探索,最终找到了Windows平台上最终的解决方案,着实不简单,不过一定走了大量的弯路。我很愿意帮助你这样主动积极探索技术的人。

    从技术上来看,以及你研究这个过程来看,你的基础还是不错的,只是,除了语言方面基础不错,在平台方面开发知识体系不全,这也是你走弯路的原因。能够通过搜索引擎得到自己的答案,这是一种能力。不过,对于你来说,我希望你能够建立起全面的知识体系,这样对你的技术提升有极大的提升。你对提问的态度也是非常正确的,这是老师的教诲,你学的很用心,做的很好。

    这个问题本身是基于Socket编程的,差不多涉及到了Socket整个技术面,只是不全面也不了解,只是查到有这么些东西。所以,要解答好你这个问题,绝对不是介绍一下完成端口这么简答。我觉得给你推荐一本书来全面学习一下,建立完整的知识体系比解释完成端口更有意义。而且,完成端口绝对不是几句话说的清楚的。

    之前写了两篇完成端口的文章:《IO完成端口分析:解惑1--基本概念辨析》  和 《IO完成端口分析:解惑2--出现并使用广泛的原因分析》,你可以先看看,但是不足以解答你的问题。

    推荐你看《Windows核心编程》。你可以下载电子版来看。这本书可以让你对Windows核心编程有一个全面的了解,其中包含了IO操作的一系列技术演变,最终发展为完成端口。在这本书中完全讲解了完成端口,可以完全解答你的问题。你可以先直接去阅读这一节,然后在全面学习一遍。

    而Socket编程本身,又是单独的一块,推荐你看《Windows Sockets 网络编程》。

    如果是学习win32编程,可以学习《Windows程序设计》。

    我们网站有一本书单,你可以参考下学习:查看书单

    如果还有疑问可以继续提问,很乐意解答你的问题。