一、前言
网络编程是一个很重要的点,毕竟现在的软件,很少有不需要网络的了,别的不说,很多软件一般都会有一个检测升级的功能。
但在了解网路编程之前,我们必须要有一个总体观念:
网络通信是对于整个电脑而言,而不单单是我们写的这个程序,我们所写的程序实际上是在调用我们电脑网络通信的能力。
也就是说,网络编程是一个与具体编程语言无关的一个概念,虽然各个语言实现的方式可能略有差别,但本质上功能、目的都是一样的。
二、网络编程基础
首先还是来考虑一个问题,我们为什么需要网络?
这个问题应该是很简单的,因为我们需要和他人交换信息、通信。
虽然目前大部分电脑的操作系统本身,都是支持多用户使用同一台电脑的。
Windows
系统也是一样,你可以在电脑上建立多个用户,且这多个用户不会互相影响
但实际上,目前个人电脑应该是占主导地位的,即自己独占一台电脑。
也就是说,如果现在我想要和朋友通信,或者从别人的网页上下载资料,就只需要让我的电脑和它的电脑通信即可,即两台电脑互相通信。
但问题来了,通信肯定需要介质来传输信息,就算是我们说话,那也需要用空气传递声波,别人才能听到!
而电脑之间的传输介质就很多了,比如无线Wifi,光纤等等。
虽然介质很多,但对于我们而言,其实可以直接抽象一下,即两个电脑之间可以直接看作,有一根线将它们连接了起来。
因为我们不需要关心各个电脑之间是用什么传输的,我们只需要知道它们能够传输信息即可。
graph LR
A[电脑]--- B[电脑]
但这只是最简化的想法,因为现实中,不可能给每个电脑或手机都拉一根线。
毕竟当前世界的电子产品数量大的惊人,所以很多时候,大家都是共用一根线来节约成本的。
graph LR
A[电脑1]--- C[公共线路]
C---B[电脑2]
A1[电脑3]---C
C---B1[电脑4]
但这时候就出现问题了,即一个电脑发送的消息,如何判断它能够准确的发送到目的计算机上呢?
因为大家都是共用的一根线传输数据!你得区分各个电脑啊!
所以这时候就有了地址,每个连上了网的电脑都会被分配一个地址,即我们常说的IP地址:
graph LR
A[电脑1 : 192.168.0.1]--- C[公共线路]
C---B[电脑2: 192.168.0.2]
A1[电脑3: 192.168.0.3]---C
C---B1[电脑4: 192.168.0.4]
当然了,上面这些地址都是我乱写的,理解一下即可
即当一个电脑想要发送信息时,只需要在信息前面添加一个IP地址,然后将这个信息发送到公有线路上。
如果接收方看到这个信息的接收地址是自己,那就接收,不是自己的话,要么转发,要么直接丢弃
比如上图中,电脑1想要给电脑4发送一条消息,那么就会在这条信息前面添加上目的地的IP地址,即192.168.0.4
。
但这条信息会发送到这条线路上的每一个电脑,当电脑2,电脑3看到这条信息目的地IP不是自己,就丢弃了,而电脑4看到这个IP地址就是自己的地址,才会接收。
上面这种通过给每个电脑都分配IP的方法,是最开始的设想,它被称为IPv4
。
但后来,谁也没想到世界的电子设备迅速增长,IP地址不够用了!
因为IPv4是用的32位二进制表示的地址,即可以表示2的32次方个地址,虽然实际上要比这个数小,但也大约可以有43亿个设备。
前面的
192.168.0.1
是二进制相应的十进制表示法,每8位分隔一下,所以四个区域中的数字,最大也只能为255
,这是为了方便我们使用。
可现在世界上的人口都有八十亿了,这肯定不够的呀!所以就出现了Ipv6
地址,用64位表示。
但由于Ipv4的基础设施已经搭建好了,想要迅速过渡到Ipv6
,就意味着需要大量更换基础设施,这样成本太高了。
所以为了正常过渡到Ipv6
,同时不影响现在使用,就出现了局域网!仅仅使用Ipv4
就能基本满足现在的需求。
专业点来说就是NAT机制,除此之外还有动态分配机制等等技术来解决这一问题。
如果你现在电脑连的Wifi
上网,那么就已经身处局域网之内了。
局域网的概念就是,不用每一个电脑都连上公网,只需要一个设备连接上公网,比如路由器,而其它设备连接路由器即可:
graph LR
A[设备1 : 公网ip1]--- C[公网ip线路]
C---B[设备2 : 公网ip2]
A1[设备3: 公网ip3]---C
C---B1[设备4: 公网ip4]
D[设备5 : 局域网ip1] --- A
D1[设备6 : 局域网ip2] --- A
这样,就能够极大缓解IP资源不够的情况!上面只是公网IP下的一层,但其实还可以继续递推嵌套下去
因为我们很可能处于局域网中的局域网。
比如我们常见的IP地址:192.168.0.1
,前面由192.168
开头的就是一个局域网IP,虽然在同一个局域网下这个IP地址不能重复,但在不同局域网下,这个IP地址是可以重复的。
比如我当前电脑就连接的Wifi,这就是在局域网下,给我分配的IP地址为192.168.3.8
:
同时也能看到,上面还有一个IPv6
地址,因为它是64位,如果用十进制就太长了,所以它用的十六进制表示。
局域网ip地址有三种:
10.0.0.0 - 10.255.255.255
172.16.0.0 - 172.31.255.255
192.168.0.0 -192.168.255.255
如果你的电脑IP在这个范围里面,那就说明你处于局域网下。
而这也就导致了,如果你的朋友也在另外一个局域网下,你两是无法直接通过对方IP地址通信的!
但为啥我们用QQ、微信也能通信呢?
那是因为这是腾讯在公网IP上架设的服务器,你发送给朋友的信息,实际上是先发送给腾讯,腾讯再帮你转发给你的朋友。
我们为什么能上网看到网页呢?
这是因为网站的服务器都是放在了公网IP上,所以你可以访问。
总结来说就是:
- 处在同一局域网中可以互相访问。
- 不同局域网之间不能直接互相访问。
- 任何网络都可以访问公网IP。
- 公网IP想要访问局域网IP,就必须局域网IP先访问自己,才能回访。
三、网络协议
一开始新手听到协议两个字,会觉得协议很高级的样子,很抽象,无法理解,但其实熟悉了之后你会发现,所谓协议不过是官方定制的标准而已,也就是规矩!
比如,上面我们已经讲了两台电脑之间传输数据,需要对方的ip地址,那么ip地址放在哪里呢?
放在数据的最前面,中间,或是最后面?似乎都是可以的,只是实现复杂度可能不同而已。
为了避免出现混乱,就出现了规矩,即协议,规定IP地址只能写在数据的最前面,放在其它地方,其它电脑就不认识。
因为根据协议,它们只看数据的最前面,不是自己的IP就丢弃。
对于我们程序开发人员而言,网络协议一般只需要知道两种即可,即我们常能看到的TCP
协议、UDP
协议。
直接介绍这种种协议的概念,可能你会有点抽象,所以这里我们还是用两个计算机的通信举例子
1.TCP
首先是TCP协议,即想要建立TCP连接的规矩,当A计算机想要和B计算机通信时:
- 根据协议,A必须先给B发送一个请求连接的消息
- B接收到了A的请求连接,就给A发送一个应答消息
- A接收到了B的应答消息,就再给B回复一个应答消息,便于B确定A收到了自己的回复
也就是说,在TCP连接的阶段,需要发送三次信息,第一次和第三次都是请求方发送方的,第二次是等待连接方发送的。
上述过程也被称为三次握手,完成了三次握手,通信双方就可以自由的发送信息了!
这个过程在C/C++网络编程中,对应着的就是connect
函数。
当发送完成了之后,想要断开连接时,比如A想要断开双方的连接:
- A向B发送断开连接请求
- B收到了之后,向A发送确认自己收到的请求
- B再向A发送断开请求
- A向B发送确认自己收到的请求
可以看到,断开连接阶段,需要发送4次信息,即一次为主动发出断开请求,一次为被动发出确认自己收到的请求。
这也被称为4次挥手。
这个过程对应的就是closesocket
函数。
至于发送、接受数据,则是通过send
、recv
等函数来完成,它们必须在连接之后才能被调用。
通过以上的过程,我们看得出来,TCP协议重在严谨!因为每次给对方发送了信息之后,都要等待对方回应它收到了信息,来确保消息无误。
所以我们对TCP就有了以下结论:
-
面向连接:只有双方建立起来连接,才能互相发送数据。
-
单播传输:即每次只能两个计算机之间进行传输数据。
-
可靠传输:因为TCP发送数据之后,都要等待对方回应自己收到的信息,所以很可靠(如果数据半路丢失,没有收到对方的回应,数据就会重新传输)
至于如何编程,可以参考本站其它具体编程语言教程的实现。
2.UDP
看到上方的TCP协议,你可能会觉得很麻烦,而且消耗资源。
因为它每次发送数据都要等待对方的回应,这数据传输的速度肯定就慢了!
在很多时候,我们可能并不需要数据太多准确,只要能用就行,比如你打微信视频时,有时候网不好就会出现卡顿、丢帧的情况,但这样也无所谓,只要能保证流畅就行嘛!
为了解决这些更强调速度的网络环境,就有了UDP协议。
这个协议非常简单,不用连接,只要你知道对方电脑的IP地址与端口,就能直接给对方发送信息!
不过前提是对方在公网上,或者与自己在同一个局域网内。
也正是因为UDP这种不需要连接的特性,它发送数据的速度非常快,而且还可以同时向多个目标发送数据!
总结来说就是:
- 非连接:不需要进行连接就能发送消息。
- 不可靠:不会对消息是否正确进行确认。
- 可广播:它可以同时向一个网段中的所有电脑发送数据。
同样的,至于如何编程,可以参考本站其它具体编程语言教程的实现。