You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
8.4 KiB
Markdown

2 years ago
# 第18讲 | 如何判断客户端的网络连接?
由于涉及到网络、脚本语言等等,这一节起,我要开始讲一些基础的、看起来比较枯燥的知识。我会尽力写得有趣生动,但是,知识的获取并不容易,即便我已经在努力去讲解,还是需要你用更多的时间去摸索和学习。
我们在前面说了Pygame的一些客户端知识如果你想让这款游戏能够在网络上传输数据接下来那就需要编写服务器端并且在客户端做客户端连接的准备。
前面我们已经用Pygame讲解了很多内容那我们客户端的网络连接我也继续使用Python来编写当然这已经和Pygame没有关系了。因为网络连接是独立的代码所以只需要直接写在游戏里就可以了。
在开始编写网络部分之前,我们需要整理一下网络的基础知识。如果我们一上来就编写网络代码,对于你来说,可能会有一些概念上的模糊。
对于网络编程或许你已经接触到了或许你只是有点概念或许你一点都没接触过。但是你或许听说过Socket套接字、TCP/IP协议、UDP协议、HTTP、HTTPS协议等等那么这些协议是不是都属于网络编程范畴还是这里面哪些部分是属于网络编程范畴呢
网络,从模型上讲,一共分为七层,从底层到最上层,分别是:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
我来分别解释一下。
* **物理层**:所谓的物理层,你可以理解为我们看到的各种网络线,也就是人肉眼能看到的物理线路,包括光纤、以前连接调制解调器的电话线等等。这些线路就是物理层。物理层有物理层的规范,比如电流、编码、帧、连接头等等。你只需要知道物理层也是存在规范的,就可以了。**物理层最主要的功能就是网络的物理连接**。
* **数据链路层**所谓的数据链路层就是建立逻辑连接然后进行硬件上的寻址操作、差错的校验然后将二进制的字节进行组合通过MAC地址进行访问比如网卡、交换机等等。你需要记住的是**在这一层要通过MAC地址来进行访问进行硬件寻址操作。**
* **网络层**网络层进行逻辑地址的寻址操作和数据链路层不同。数据链路是使用硬件寻址操作而网络层是使用逻辑地址寻址比如路由器、防火墙、多层交换机等等。我们最熟悉的IPv4202.101.253.233、IPv6、ARP等等都属于这一层。你在这里需要记住的是**网络层是逻辑寻址操作会用到ARP、IPv4等等协议。**
* **传输层**在编程中最常用到的TCP、UDP等等协议都在这一层进行操作它首先定义了数据传输的协议端口号以及一些错误的检测。
* **会话层**:会话层在传输层之上,它就在客户端和服务器端。严谨地说,就是本地机器和远端机器之间的会话,比如要进行断点续传这些操作,就属于会话层的范畴。
* **表示层**:表示层很容易理解,就是数据的传输,然后展现在电脑上。比如图片的传输和显示、网络地址的加密等等。
* **应用层**应用层就是提供给电脑用户的各种网络应用比如你自己编写的网络软件、FTP软件、Telnet、浏览器等等。
以上这些点你要硬性记住的话,会比较困难。我教给你一个方法。
首先,我们想象一段从网线过来一段数据,网线就是“物理层”,那么数据需要找到一个门牌号,这个门牌号是一个硬件地址,可能是你的电脑网卡,也可能是你公司的交换机。这些数据需要把这些门牌地址连接起来,这就是“数据链路层”。
随后这些数据找到门牌号后就需要分发到逻辑地址比如路由器或者你的IP地址这些逻辑地址就是网络地址这就是“网络层”。
经过网络层后就要看这是什么数据是TCP协议的还是UDP协议的。知道了协议后才可以传输数据所以这个是“传输层”。
那么在传输的过程中,可能会中断,所以我们需要登录服务器,断点续传进行重新传输,这些属于机器和机器之间的会话,所以是“会话层”。
传输完数据后,我们就会在电脑里显示这个内容,是一幅图片呢,还是一段电影?这个需要表示出来,所以是“表示层”。
最后,我们将这个一整套的东西,写成了一个应用,这就是“应用层”。
虽然这么表述起来,有许多不精确不严谨的地方,但是通过这段话能让你很快记住这个七层网络模型,对你将来的编程有很大的帮助。
Python支持Socket编程也就是支持TCP、UDP等协议的编程也支持更上层的编程比如HTTP协议等等。在今天的内容中我们要用到TCP编程。至于为什么要使用TCP有这样几个原因
1. TCP保证连接的**正确性**。在建立TCP连接的时候需要经过三次握手连接这一方发送SYN协议被连接方返回SYN+ACK协议最后连接方再返回ACK协议
2. TCP保证如果在一定时间内没有收到对方的信息就重发消息保证消息传输的**可靠性**
3. TCP可以进行**流量控制**。它拥有固定大小的缓冲池TCP的接收方只允许另一方发送缓冲池内所接纳的数据大小。
TCP还有其他更多的保证传输可靠性的内容和标准我在这里不做更多的阐述。另外使用TCP可以进行长时间的连接在客户端和服务器端之间进行不停地交互。在交互过程中服务器端发送数据给客户端客户端就能做出相应的回应。
在Python中编写TCP协议的代码比之使用C/C++更为方便。因为C/C++需要初始化一系列的内容然后进行顺序的流程化绑定设置网络参数最后进行发送和接收操作在结束的时候进行资源的回收。而在Python这里只需要设置协议和IP地址就可以实现TCP协议编程。我们来看一段代码。
```
import socket
class go_sock(object):
ip = ""
port = 0
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def __init__(self):
object.__init__(self)
def connect(self, ip, port):
self.ip = ip
self.port = port
self.sock.connect_ex((ip, port))
def close(self):
self.sock.close()
```
我在这里编写了一个类这个类将TCP的内容封装在了类中这样我们的网络代码能在游戏中方便地初始化使用起来就很方便。
首先我们看到在类里面定义了ip、port、sock这三个变量这三个变量分别是对应IP地址、端口号以及socket句柄。在类里我们直接将sock初始化为socket类其中socket类填写的内容中参数1是服务器之间的网络通信参数2是流Socket这里指的是TCP协议。
在初始化完成了之后我们看到connect函数。在函数里面我们看到参数对变量的初始化其中sock句柄调用了标准socket函数sock.connect\_ex这个函数负责与对方进行一个连接。
最后的函数是close关闭操作在任务完成之后你可以调用close函数进行socket句柄的关闭。
我们可以这样使用这个类。
```
_inet = go_sock()
_inet.connect("115.231.74.62", 21)
_inet.sock.recv(100)
```
在这里,我们可以简单测试一下某些应用服务器,然后接收返回内容。这个类的封装工作到此就告一个段落,更多的网络服务和交互的编写,我将在下一节阐述。
## 小结
今天我们学习了网络的七层模型结构以及我们将要在游戏中使用的TCP协议的编程。
* 我用了一个传输过程介绍了七层每一层做的事情,这个你一定要牢记。
* 我们使用Python封装了Socket库的细节内容只需要直接编写connect代码就可以进行数据的接收和发送操作了。
* 选择TCP协议是因为它安全可靠能保证游戏传输的过程中不出错。
现在,我给你留一个小问题吧。
如果我们要使用UDP来编写这个网络服务该如何保证数据的准确性呢选择UDP协议的优势在哪里
欢迎留言说出你的看法。我在下一节的挑战中等你!