关于网络编程Word下载.docx
《关于网络编程Word下载.docx》由会员分享,可在线阅读,更多相关《关于网络编程Word下载.docx(12页珍藏版)》请在冰豆网上搜索。
![关于网络编程Word下载.docx](https://file1.bdocx.com/fileroot1/2022-11/15/15bd9d30-d71b-4ab9-bd04-9afb54c66f6f/15bd9d30-d71b-4ab9-bd04-9afb54c66f6f1.gif)
这台PC上还运行着一个程序,负责生成比分数据的静态页面,通过FTP上传发布到某门户网站的体育频道。
系统中还有一个录入赛程(参赛队,运动员,出场顺序等)数据库的程序,运行在数据库服务器上。
算下来整个系统有十来个程序,运行在二十多台设备(PC和PDA)上,还要考虑可靠性。
将来有机会把这个小系统仔细讲一讲,挺有意思的。
这是我第一次写实际项目中的网络程序,当时写下来的感觉是像写命令行与用户交互的程序:
程序在命令行输出一句提示语,等待客户输入一句话,然后处理客户输入,再输出下一句提示语,如此循环。
只不过这里的“客户”不是人,而是另一个程序。
在建立好TCP连接之后,双方的程序都是read/write循环(为求简单,我用的是blocking读写),直到有一方断开连接。
第二次是2010年编写muduo网络库,我再次拿起了SocketsAPI,写了一个基于Reactor模式的C++网络库。
写这个库的目的之一就是想让日常的网络编程从SocketsAPI的琐碎细节中解脱出来,让程序员专注于业务逻辑,把时间用在刀刃上。
Muduo网络库的示例代码包含了几十个网络程序,这些示例程序都没有直接使用SocketsAPI。
在此之外,无论是实习还是工作,虽然我写的程序都会通过TCP协议与其他程序打交道,但我没有直接使用过SocketsAPI。
对于TCP网络编程,我认为核心是处理“三个半事件”,见《Muduo网络编程示例之零:
前言》中的“TCP网络编程本质论”。
程序员的主要工作是在事件处理函数中实现业务逻辑,而不是和SocketsAPI较劲。
这里还是没有说清楚“网络编程”是什么,请继续阅读后文“网络编程的各种任务角色”。
学习网络编程有用吗?
以上说的是比较底层的网络编程,程序代码直接面对从TCP或UDP收到的数据以及构造数据包发出去。
在实际工作中,另一种常见的情况是通过各种clientlibrary来与服务端打交道,或者在现成的框架中填空来实现server,或者采用更上层的通信方式。
比如用libmemcached与memcached打交道,使用libpq来与PostgreSQL打交道,编写Servlet来响应http请求,使用某种RPC与其他进程通信,等等。
这些情况都会发生网络通信,但不一定算作“网络编程”。
如果你的工作是前面列举的这些,学习TCP/IP网络编程还有用吗?
我认为还是有必要学一学,至少在troubleshooting的时候有用。
无论如何,这些library或framework都会调用底层的SocketsAPI来实现网络功能。
当你的程序遇到一个线上问题,如果你熟悉SocketsAPI,那么从strace不难发现程序卡在哪里,尽管可能你没有直接调用这些SocketsAPI。
另外,熟悉TCP/IP协议、会用tcpdump也大大有助于分析解决线上网络服务问题。
在什么平台上学习网络编程?
对于服务端网络编程,我建议在Linux上学习。
如果在10年前,这个问题的答案或许是FreeBSD,因为FreeBSD根正苗红,在2000年那一次互联网浪潮中扮演了重要角色,是很多公司首选的免费服务器操作系统。
2000年那会儿Linux还远未成熟,连epoll都还没有实现。
(FreeBSD在2001年发布4.1版,加入了kqueue,从此C10k不是问题。
)
10年后的今天,事情起了变化,Linux成为了市场份额最大的服务器操作系统(http:
//en.wikipedia.org/wiki/Usage_share_of_operating_systems)。
在Linux这种大众系统上学网络编程,遇到什么问题会比较容易解决。
因为用的人多,你遇到的问题别人多半也遇到过;
同样因为用的人多,如果真的有什么内核bug,很快就会得到修复,至少有workaround的办法。
如果用别的系统,可能一个问题发到论坛上半个月都不会有人理。
从内核源码的风格看,FreeBSD更干净整洁,注释到位,但是无奈它的市场份额远不如Linux,学习Linux是更好的技术投资。
可移植性重要吗?
写网络程序要不要考虑移植性?
这取决于项目需要,如果贵公司做的程序要卖给其他公司,而对方可能使用Windows、Linux、FreeBSD、Solaris、AIX、HP-UX等等操作系统,这时候考虑移植性。
如果编写公司内部的服务器上用的网络程序,那么大可只关注一个平台,比如Linux。
因为编写和维护可移植的网络程序的代价相当高,平台间的差异可能远比想象中大,即便是POSIX系统之间也有不小的差异(比如Linux没有SO_NOSIGPIPE选项),错误的返回码也大不一样。
我就不打算把muduo往Windows或其他操作系统移植。
如果需要编写可移植的网络程序,我宁愿用libevent或者JavaNetty这样现成的库,把脏活累活留给别人。
网络编程的各种任务角色
计算机网络是个bigtopic,涉及很多人物和角色,既有开发人员,也有运维人员。
比方说:
公司内部两台机器之间ping不通,通常由网络运维人员解决,看看是布线有问题还是路由器设置不对;
两台机器能ping通,但是程序连不上,经检查是本机防火墙设置有问题,通常由系统管理员解决;
两台机器能连上,但是丢包很严重,发现是网卡或者交换机的网口故障,由硬件维修人员解决;
两台机器的程序能连上,但是偶尔发过去的请求得不到响应,通常是程序bug,应该由开发人员解决。
本文主要关心开发人员这一角色。
下面简单列出一些我能想到的跟网络打交道的编程任务,其中前三项是面向网络本身,后面几项是在计算机网络之上构建信息系统。
1.开发网络设备,编写防火墙、交换机、路由器的固件firmware
2.开发或移植网卡的驱动
3.移植或维护TCP/IP协议栈(特别是在嵌入式系统上)
4.开发或维护标准的网络协议程序,HTTP、FTP、DNS、SMTP、POP3、NFS
5.开发标准网络协议的“附加品”,比如HAProxy、squid、varnish等webloadbalancer
6.开发标准或非标准网络服务的客户端库,比如ZooKeeper客户端库,memcached客户端库
7.开发与公司业务直接相关的网络服务程序,比如即时聊天软件的后台服务器,网游服务器,金融交易系统,互联网企业用的分布式海量存储,微博发帖的内部广播通知,等等
8.客户端程序中涉及网络的部分,比如邮件客户端中与POP3、SMTP通信的部分,以及网游的客户端程序中与服务器通信的部分
本文所指的“网络编程”专指第7项,即在TCP/IP协议之上开发业务软件。
面向业务的网络编程的特点
跟开发通用的网络程序不同,开发面向公司业务的专用网络程序有其特点:
·
业务逻辑比较复杂,而且时常变化
如果写一个HTTP服务器,在大致实现HTTP/1.1标准之后,程序的主体功能一般不会有太大的变化,程序员会把时间放在性能调优和bug修复上。
而开发针对公司业务的专用程序时,功能说明书(spec)很可能不如HTTP/1.1标准那么细致明确。
更重要的是,程序是快速演化的。
以即时聊天工具的后台服务器为例,可能第一版只支持在线聊天;
几个月之后发布第二版,支持离线消息;
又过了几个月,第三版支持隐身聊天;
随后,第四版支持上传头像;
如此等等。
这要求程序员能快速响应新的业务需求,公司才能保持竞争力。
不一定需要遵循公认的通信协议标准
比方说网游服务器就没什么协议标准,反正客户端和服务端都是本公司开发,如果发现目前的协议设计有问题,两边一起改了就是了。
程序结构没有定论
对于高并发大吞吐的标准网络服务,一般采用单线程事件驱动的方式开发,比如HAProxy、lighttpd等都是这个模式。
但是对于专用的业务系统,其业务逻辑比较复杂,占用较多的CPU资源,这种单线程事件驱动方式不见得能发挥现在多核处理器的优势。
这留给程序员比较大的自由发挥空间,做好了横扫千军,做烂了一败涂地。
性能评判的标准不同
如果开发httpd这样的通用服务,必然会和开源的Nginx、lighttpd等高性能服务器比较,程序员要投入相当的精力去优化程序,才能在市场上占有一席之地。
而面向业务的专用网络程序不一定有开源的实现以供对比性能,程序员通常更加注重功能的稳定性与开发的便捷性。
性能只要一代比一代强即可。
网络编程起到支撑作用,但不处于主导地位
程序员的主要工作是实现业务逻辑,而不只是实现网络通信协议。
这要求程序员深入理解业务。
程序的性能瓶颈不一定在网络上,瓶颈有可能是CPU、DiskIO、数据库等等,这时优化网络方面的代码并不能提高整体性能。
只有对所在的领域有深入的了解,明白各种因素的权衡(trade-off),才能做出一些有针对性的优化。
几个术语
互联网上的很多口水战是由对同一术语的不同理解引起的,比我写的《多线程服务器的适用场合》就曾经人被说是“挂羊头卖狗肉”,因为这篇文章中举的master例子“根本就算不上是个网络服务器。
因为它的瓶颈根本就跟网络无关。
”
网络服务器
“网络服务器”这个术语确实含义模糊,到底指硬件还是软件?
到底是服务于网络本身的机器(交换机、路由器、防火墙、NAT),还是利用网络为其他人或程序提供服务的机器(打印服务器、文件服务器、邮件服务器)。
每个人根据自己熟悉的领域,可能会有不同的解读。
比方说或许有人认为只有支持高并发高吞吐的才算是网络服务器。
为了避免无谓的争执,我只用“网络服务程序”或者“网络应用程序”这种含义明确的术语。
“开发网络服务程序”通常不会造成误解。
客户端?
服务端?
在TCP网络编程里边,客户端和服务端很容易区分,主动发起连接的是客户端,被动接受连接的是服务端。
当然,这个“客户端”本身也可能是个后台服务程序,HTTPProxy对HTTPServer来说就是个客户端。
客户端编程?
服务端编程?
但是“服务端编程”和“客户端编程”就不那么好区分。
比如Webcrawler,它会主动发起大量连接,扮演的是HTTP客户端的角色,但似乎应该归入“服务端编程”。
又比如写一个HTTPproxy,它既会扮演服务端——被动接受webbrowser发起的连接,也会扮演客户端——主动向HTTPserver发起连接,它究竟算服务端还是客户端?
我猜大多数人会把它归入服务端编程。
那么究竟如何定义“服务端编程”?
服务端编程需要处理大量并发连接?
也许是,也许不是。
比如云风在一篇介绍网游服务器的博客
我认为,“服务端网络编程”指的是编写