libcurl是C语言写成的网络编程工具库,asio是C++写的网络编程的基础类型库
libcurl只用于客户端,asio既可以写客户端,也可以写服务端
libcurl实现了HTTP\FTP等应用层协议,但asio却只实现了传输层TCP/UDP等协议。
在学习http时介绍过"OSI网络七层"协议,但实际应用更多的是"TCP/IP五层协议",在后者的分层中,HTTP和FTP均为在TCP均为在TCP之上实现的协议,如下图13-19所示
如图13-19所示,HTTP和FTP基于TCP实现,HTTP针对网页内容传输的应用,FTP针对文件数据传输的应用,分别定义非常不同的连接、交互方式以及报文格式。
假设我们想写一个下载新浪网页的客户端,使用libcurl,它已经帮我们实现并封装了HTTP客户端的相关工作,比如如何打包请求报文,如何解析服务端返回的报文等;但如果改为使用 asio,这一切都需要我们编写代码。
网络通信协议存在分层,和写程序时进行分层设计的原因相同,都是为了解决"通用"和"定制"之间的矛盾。
上层协议用于满足个性通信,下层协议用于满足共性通信。
我们可以将TCP协议理解为是在马路行车需要的约定和技巧,比如靠右行驶,红灯停,绿灯行,夜间过十字路口打双闪......
那HTTP协议可以理解为在马路上驾驶自动档小轿车需要的约定和技巧,而FTP就是在马路上驾驶有挂斗的大货车需要的约定和技巧。
TCP和UDP都是传输层的协议,全称分别是"Transmission Control Protocol(传输控制协议)"和"User Datagram Protocol(用户数据报协议)"。二者重要的差别在于基于前者(TCP)的网络通信被称为"有连接"的通信,基于后者(UDP)的被称为"无连接"的通信。
可以用"电话"比喻"有连接"通信,用"信件"比喻"无连接"通信。
对于"有连接"通信,自然就有建立连接和断开连接的过程。TCP协议建立连接需要由客户端发起,服务端接受(当然也可以拒绝,从而无法建立连接)。为了在复杂的网络环境下保障建立连接的正确性,二者之间需要经过三次报文收发,俗称"三次握手"。
一旦连接建立,双方想痛快断开,则需要"四次握手"。当然会有意外情况造成连接硬生生断开,比如网线被拔了。不管怎样,所有未经四次交互确认的连接断开,都是"不优雅"的断开,相对的,正常断开的过程被称为"优雅的断开"。
不仅建立连接需要有确认,每一次上层应用数据的收发,
有连接的通信过程,都会有确认机制,在没有收到对端(peer)的确认之前,本地端(local)不会发新数据,最多是等到超时重发。
无连接的通信则不一样,发送方可以可劲儿地发,不管也管不了接收方有没有收到。
当然,如有需要,上层应用可以在无连接的传输层协议之上,尽量模拟有连接确认的重发等机制。但这真的是非常难喝繁琐的,所以当我们的应用确实很在意数据收发的可靠性,应该尽量使用TCP协议
【课堂作业】了解学习TCP/UDP的更多知识:
①TCP/UDP更多关于有连接、无连接的区别;
②二者的更多区别以及各自适用的场景;
③TCP建立和断开连接的过程;
④二者具体的报文格式;
⑤TCP之上的更多协议。
⑥什么叫IP地址,什么叫域名地址;
⑦网卡、路由器、防火墙等的作用和基本工作原理。
不管是UDP还是TCP通信,通信双方都可以分为客户端和服务端,其中客户端通常指通信的发起者。
对于TCP,它有明确的区分方法,即发起连接的一方。
对于UDP,客户端和服务端的区分并不明显,简单但不精确的理解是:将第一次发送报文的一方当做客户端。
区分客户和服务端的另一方法,服务端是可以以一对多的一方,典型的如TCP中服务端可以接受并同时处理多个连接。
注意,这里提的客户端和服务端都是指网络编程中的独立模块,而非对应到通信双方的进程。
一个进程可能既是通信的客户端,也是通信的服务端,一个进程也可以包含多个通信的客户端或服务端。
现实网络还存在另外一个复杂性,即网络和网络之间的可见性和连通性。
简单的两个结论:服务端必然要部署在客户端可以主动访问的地方,但客户端可以隐藏在服务端可能看不到摸不着的地方。理解这一事实的正确方法是上网查阅更多有关"互联网""局域网"和"广域网"等知识。
TCP服务端必须可见,因此服务端必须有一个客户端可到达的地址。通常是指一个主机地址和一个端口。主机地址通常是一个域名或一个IP地址,用于指向一台主机。端口则是一个数字编号,有效范围1~65535,用于区分同一台主机内不同的服务端。
可以把服务器想象成一座楼(假设楼栋编号为女78号),有一面墙总共挖了65535个带着编号的窗(端)口,各个服务程序支着大大的耳朵贴近特定号码的端口上监听。
"监听"在此处的翻译是listen,和select一样是一个socket函数。服务端程序一开始监听,就算是准备就绪了。
客户端就是对面的一堆男生楼。开始有人在喊:"女78楼80号端口的王美丽,我是男25楼520号的张有钱,我要和你申请建立连接,请接收。"
女方心里暗自冷笑,"有钱就像连接美丽?"女方拒绝后,男方再三尝试后终于放弃。接着传来"女78楼80号端口的王美丽,我是男680楼52013号的付二袋,我要和你申请建立连接,请接收。"王美丽欣然接受连接。
"接受"在此处的翻译是accept,也是一个socket函数。