(本文针对的是windows,linux下基于c++语言的网络编程) linux
我从事的是企业级的软件开发,纵观当今的企业级软件,单机模型已经愈来愈少,更多的是C/S模型,目前client和server之间通讯是经过socket技术来实现的。
上面提到了socket技术,天然要学习TCP/IP协议,对于TCP/IP的理论,学习Richard的
《TCP/IP详解 卷1:协议》我认为是不二的选择,这本书涵盖内容不少,若是对于只是实现C/S通讯的网络库而言,仅须要了解其中介绍UDP和TCP的章节就好,扎实的理论基础会为你之后遇到网络传输中出现的问题给予很好的解释,也便于你解决这些问题。理论联系实现,仍是Richard的
《UNIX网络编程 卷1:套接口API》(俗称UNP1),这本书我一直在看,可是还没看完,我认为这是网络编程的圣经,你掌握了这本书,基本也就掌握了网络编程,甚至细枝末节也能覆盖到。
(如下只涉及TCP协议)
紧接着学习转为实践,想一想网络通讯的场景:一个server要对应成千上万,甚至十万..个客户,这样必需要考虑到server的处理能力。
最简单的模型就是你用
一个进程来处理全部的客户端链接,my god!你想一想,在处理过程当中若是有上百个链接同时请求服务,咱们采用这种模式,首先下一个链接要等着上一个链接处理完(同步),这个在处理的链接还颇有可能阻塞在数据操做(I/O)上,这样处理链接的效率之差及客户端的响应之慢我想几乎没有人能忍受吧。
好,为了提升效率,咱们改进一下,
对每个客户链接产生一个线程(windows)或进程(linux)来处理,抛开线程或进程的上下文切换损耗不谈,也不谈SMP,就单单看产生成千上百个线程和进程的可行性,对不起,咱操做系统但是有线程或进程资源上限的。
为了解决线程频繁切换形成的资源损耗和资源数限制问题,
咱们再改进一下,采用一个线程池来处理部分链接,其余链接排队等候,毕竟咱cpu很少,同时也就能处理那么几个链接,响应效率和处理效率依然提不上去。
想一个问题,其实咱们的网络耗时通常都是在数据操做上(I/O),为了增长客户端的响应,
咱们能够把一次网络接入分为处理链接的线程和进行逻辑处理的线程,这样就能够极大地提升客户端的响应,可是记住必定要在逻辑处理线程中维护住这个链接的会话。这样仿佛还不错,no,no,其实也很差,你并不知道何时有数据到来须要处理,你必需要轮询来肯定可不能够进行数据操做....,效率仍是很差啊。
好了,咱不本身首创技术了,
选用经典的Reactor和Proactor并发编程模式,他们都是基于事件驱动的,咱呢就是把网络中须要处理的事件注册到事件管理器中去(好比网络行为事件,IO操做事件.....),而后等事件状态就绪了,他就用回调的方式通知咱去处理,怎么样,这样至少CPU不会闲着了,只用一个线程就能够处理几乎全部的事件了。可是Reactor和Proactor仍是有很大区别的,Reactor对于I/O这一步是须要本身处理的,可是Proactor对于I/O这一步是由操做系统完成的,而后把完成事件通知你,而后你就能够进行下一步操做了(好比从缓冲区buf里读数据),比本身操做I/O这种方式快多了吧。目前,我在windows下写网络库采用的是Proactor模式:用windows本身提供的完成端口模型(
IOCP)实现,在linux下,因为linux没有很好的异步I/O机制,只好采用Reactor方式了:使用的是linux特有的
epoll。谈一些我本身的见解:从个人理解上,对于大部分网络库而言,不少都是I/O密集型的,这样仿佛采用Proactor模式更有优点,可是linux下没有和windows下IOCP相似的机制,可是能够采用epoll加任务队列的方式实现一套,可是仿佛很复杂,我想本身实现就算了吧。好在“山穷水复疑无路,柳暗花明又一村”,boost asio 已经为咱们封转好了windows和linux下的Proactor实现,windows采用的是完成端口,linux下采用的是epoll加任务队列的方式实现。下一步我准备把目前linux下采用epoll方式实现的Reactor网络库改成boost asio的实现。
今天,对于网络编程先整体而且归纳的介绍下吧,其实还有不少问题没有涉及,我本人对网络编程十分的感兴趣,如今也在从事这方面的工做,因此之后有机会但愿和你们一块儿分享一些更细致全面的知识,鉴于本人水平有限,但愿你们能对文章中出现的错误给予批评指正,咱们一块儿进步......