Python 网络编程(一)

本文涉及的产品
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
简介: Python 网络编程(一)

Python 网络编程(一)


网络概述

现在的生活离不开网络,例如手机,电脑,平板,都是网络的代名词,通过一些APP,浏览器,获取大量的信息如文字、声音、视频,这都是从网络的某个地址存在的或者是网络的另一端某个用户通过设备共享的,那么什么是网络?是通过又是如何共享的尼?网络是由若干节点和连接这些节点的链路构成,表示诸多对象及其相互联系,像我们平常办理宽带与手机办卡上网,都是通过向某一服务商缴费注册连上他们的设备,下载相应的聊天软件和浏览器就可以上网与他人交流、获取资源、浏览一些网络信息。

当然还有一些其他的网络内容包含的范围非常大,只是没有接触到。现在的信息非常的发达,我们接触到的信息也非常的多,那么我们的信息是怎么完成网络共享,资源共享的尼?

我们第一时间就是想到,浏览器,微信,QQ,这都是非常常见的网络信息传递和获取的方式,那是怎么传递的尼?网络又是一个什么样的?这里将引入网络模型的概念,常见的七层 OSI 模型与四层 TCP/IP 模型诠释了网络的连接与资源传递,当一个用户或一台主机向另一个用户或一台主机获取或是发送资源,中间的连接方式就封装在模型概念上传输或连接。

OSI 模型

网络

1983年,国际标准化组织(International Organization for Standardization,ISO)发布了著名的 ISO/IEC7498 标准,也就是开放式系统互连参考模型(Open System Interconnection Reference Model,OSI)。这个标准定义了网络的七层框架,试图使计算机在整个世界范围内实现互联。在 OSI 中,网络体系结构被分成以下7层。如下图

物理层:定义了通信设备的传输规范,规定了激活、维持和关闭通信节点之间的机械特性、电气特性和功能特性等。此层为上层协议提供了一个传输数据的物理媒介。简单的描述是将数据转换为可通过物理介质传送的电子信号 相当于快递公司中的搬运工人。

数据链路层:定了数据封装以及传送的方式。这个层次的数据单位称为帧。数据链路层包括两个重要的子层:逻辑链路控制层(Logic Link Control,LLC)和介质访问控制层(Media Access Control,MAC)。LLC 用来对节点间的通信链路进行初始化,并防止链路中断,确保系统的可靠通信。而MAC则用来检测包含在数据帧中的地址信息。这里的地址是链路地址或物理地址,在设备制造的时候设置的。网络上的两种设备不能够包含相同的物理地址,否则会造成网络信息传送失败。简单的描述是决定访问网络介质的方式。在此层将数据分帧,并处理流控制。本层指定拓扑结构并提供硬件寻址,相当于快递公司中的装拆箱工人。

网络层:定义了数据的寻址和路由方式。这一层负责选择子网间的数据路由,并实现网络互连等功能。简单的描述是使用权数据路由经过大型网络,相当于快递公司中的排序工人按指定的省市地区分类。

传输层:为数据提供端到端传输。这是比网络层更高的层次,是主机到主机的层次。传输层将对上层的数据进行分段并进行端到端传输。另外,还提供差错控制和流量控制问题。简单的描述是提供终端到终端的可靠连接,相当于公司中跑快递点邮寄东西的人员。

会话层:用来为通信的双方制定通信方式,包括建立和拆除会话。另外,此层将会在数据中插入校验点来实现数据同步。简单的描述允许用户使用简单易记的名称建立连接 相当于公司中收寄快递、包裹与拆包裹的前台服务人员。

表示层:为不同的用户提供数据和信息的转换。同时还提供解压缩和加解密服务。这一层保证了两个主机的信息可以互相理解。简单的描述是协商数据交换格式 相当公司中替领导拿或寄快递的助理。

应用层:控制着用户绝大多数对于网络应用程序的访问,提供了访问网络服务的接口。简单的描述是用户的应用程序和网络之间的接口。

数据信息的实际流程使用的是实线的箭头标记的,而层次的关系则使用的是虚线来标记的。在 OSI 的七层模型中,数据访问只会在上下的两层之间进行。

这是一个通用的网络系统模型,并不是一个协议定义。所以实际上 OSI 模型从来没有被真正实现过。但是,由于其模型的广泛指导性,现在的网络协议都已经纳入了 OSI 模型的范围之内。在其模型中,从下至上层次依次增加,其中物理层为第一层,数据链路层为第二层,以此类推,应用层为第七层。在称呼 OSI 协议中的模型的时候,可以直接使用本来的名字,也可以直接使用数字层次。

TCP/IP 模型

实际上在 OSI 模型出现之前,就已经有了 TCP/IP 的研究和实现。时间 早可以追溯到20世纪70年代,为互联网的早的通信协议。TCP 为传输层的协议,而 IP 则为网络层的协议。两个层次中有代表性的协议组合代表了一系列的协议族,还包括有 ARP、ICMP 和 UDP 协议等。由于 TCP/IP 协议出现的比 OSI 早,所以并不符合 OSI 模型,对应关系如下

图的左边为 OSI 模型,而右边为 TCP/IP 模型。从图中可以看到,TCP/IP 模型并不关心 IP 层以下的组成,而是将数据输出统一成了网络接口层。这样,IP 层只需要将数据发往网络接口层就可以了,而不需要关心下层具体的操作。而在 OSI 模型中,则将这些功能分成了数据链路层和物理层,而且还进行了进一步的划分。在传输层和网络层大部分还是一致的。而对于 OSI 中的上面三层,则在 TCP/IP 模型中将其合并成了应用层。

在现在的 Internet 中,主要采用的都是 TCP/IP 协议。这已经成为互联网上通信的事实标准。现在,TCP/IP协议已经可以运行在各种信道和底层协议之上。在 TCP/IP 模型中, 主要的两个协议 TCP/IP 分别属于传输层和互联网层。在互联网层中,标志主机的方法是使用IP地址,如192.168.0.1就是一个内网主机的 IP 地址。通过对 IP 地址的类别划分,可以将整个 Internet 网络划分成不同的子网。而在传输层中,标志一个应用的方法是通过端口号来标志的,这些不同的端口号则表示不同的应用。例如80端口一般来说是 HTTP 协议,而23号端口则是 Telnet 协议等。这样,在 TCP/IP 模型中,标志一个主机上的应用则可以通过地址-端口对来表示,后面也会详细的说明协议具体情况

协议

协议也叫网络协议,网络协议是通信计算机双方必须共同遵从的一组约定。如怎么样建立连接、怎么样互相识别等。只有遵守这个约定,计算机之间才能相互通信交流。它的三要素是:语法、语义、时序。为了使数据在网络上从源到达目的,网络通信的参与方必须遵循相同的规则,这套规则称为协议(protocol),它 终体现为在网络上传输的数据包的格式。协议往往分成几个层次进行定义,分层定义是为了使某一层协议的改变不影响其他层次的协议。

遵循我们的 OSI 模型作为参考,常用到的协议有:网络层协议 IP、传输层协议 TCP 和 UDP、应用层协议 HTTP等常用协议。下面简述一下协议的基本的概念和理解

IP 协议

IP 是整个 TCP/IP 协议族的核心,也是构成互联网的基础。IP 位于 TCP/IP 模型的网络层(相当于OSI模型的网络层),对上可 送传输层各种协议的信息,例如 TCP、UDP 等;对下可将 IP 信息包放到链路层,通过以太网、令牌环网络等各种技术来 传送。 为了能适应异构网络,IP 强调适应性、简洁性和可操作性,并在可靠性做了一定的牺牲。IP 不保证分组的交付时限 和可靠性,所传送分组有可能出现丢失、重复、延迟或乱序等问题;

目前的 IP 版本有4和6,如 IPv4 和 IPv6,目前 流行的就是 IPv4,有十进制和二进制两种表示方法。分别是:

点分四组十进制。每一组范围是[0~255],如:255.255.255.255

二进制,如:11111111 11111111 11111111 11111111

IPv6 地址长度是128位,由8块(或8个字段)组成,每一块都包含四个16进制数,每块由冒号分隔。

有以下特点:

一个块中前导的0不必书写。

全0的块可以省略,并用符号::代替。

IPv6 可以兼容 IPv4 地址,即可以用 IPv6 格式表示 IPv4 地址。表示方式为:IPv6 块值为ffff,其后面紧跟“点分四组”的 格式。如:::ffff:10.0.0.1可以代表 IPv4:10.0.0.1

IPv6 的低32位通常采用点分四组的表示法。:::ffff:10.0.0.1

IP 地址是用来识别网络上的设备,因此,IP 地址是由网络地址与主机地址两部分所组成

网络地址可用来识别设备所在的网络,网络地址位于 IP 地址的前段。当组织或企业申请 IP 地址时,所获得的并非 IP 地址 而是取得一个唯一的、能够识别的网络地址。同一网络上的所有设备,都有相同的网络地址。IP 路由的功能是根据 IP 地址中的网络地址,决定要将 IP 信息包送至所指明的那个网络

主机地址位于 IP 地址的后段,可用来识别网络上设备。同一网络上的设备都会有相同的网络地址,而各设备之间则是以主机地址来区别。

以下单只 IP 协议的地址结构图

A 类 IP 地址

一个 A 类 IP 地址由1字节的网络地址和3字节主机地址组成,网络地址的 高位必须是“0”,地址范围1.0.0.1-126.255.255.254

二进制表示为:00000001 00000000 00000000 00000001 - 01111110 11111111 11111111 11111110

可用的 A 类网络有126个,每个网络能容纳1677214个主机

B 类 IP 地址

一个 B 类 IP 地址由2个字节的网络地址和2个字节的主机地址组成,网络地址的 高位必须是“10”,地址范围128.1.0.1-191.255.255.254

二进制表示为:10000000 00000001 00000000 00000001 - 10111111 11111111 11111111 11111110

可用的 B 类网络有16384个,每个网络能容纳65534主机

C 类 IP 地址

一个 C 类 IP 地址由3字节的网络地址和1字节的主机地址组成,网络地址的 高位必须是“110” 范围192.0.1.1-223.255.255.254

二进制表示为: 11000000 00000000 00000001 00000001 - 11011111 11111111 11111110 11111110

C 类网络可达2097152个,每个网络能容纳254个主机

D 类 IP 地址用于多点广播

D 类 IP 地址第一个字节以“1110”开始,它是一个专门保留的地址。

它并不指向特定的网络,目前这一类地址被用在多点广播(Multicast)中多点广播地址用来一次寻址一组计算机

地址范围224.0.0.1-239.255.255.254

E 类 IP 地址以“1111”开始,为将来使用保留

E 类地址保留,仅作实验和开发用

私有 ip

在这么多网络IP中,国际规定有一部分IP地址是用于我们的局域网使用,也就是属于私网IP,不在公网中使用的,它们的范围是:

10.0.0.0 ~ 10.255.255.255
176.16.0.0 ~ 176.16.255.255
192.168.0.0 ~ 192.168.255.255

注意

IP地址127.0.0.1~127.255.255.255用于回路测试,如:127.0.0.1可以代表本机IP地址,用 http://127.0.0.1 就可以测试本机中配置的Web服务器。

子网掩码

要想理解什么是子网掩码,就不能不了解 IP 地址的构成。互联网是由许多小型网络构成的,每个网络上都有许多主机, 这样便构成了一个有层次的结构。IP 地址在设计时就考虑到地址分配的层次特点,将每个IP地址都分割成网络号和主机号两部分,以便于 IP 地址的寻址操作。

IP 地址的网络号和主机号各是多少位呢?

如果不指定,就不知道哪些位是网络号、哪些是主机号,这就需要通过子网掩码来实现。

子网掩码不能单独存在,它必须结合 IP 地址一起使用。

子网掩码只有一个作用,就是将某个 IP 地址划分成网络地址和主机地址两部分子网掩码的设定必须遵循一定的 规则。

与 IP 地址相同,子网掩码的长度也是32位,

左边是网络位,用二进制数字“1”表示;

右边是主机位,用二进制数字“0”表示。

假设 IP 地址为“192.168.1.1”

子网掩码为“255.255.255.0”。

其中,“1”有24个,代表与此相对应的 IP 地址左边24位是网络号;

“0”有8个,代表与此相对应的 IP 地址右边8位是主机号。

这样,子网掩码就确定了一个 IP 地址的32位二进制数字中哪些是网络号、哪些是主机号。

这对于采用 TCP/IP 协议的网络来说非常重要,只有通过子网掩码,才能表明一台主机所在的子网与其他子网的关系,使网络正常工作。

常用的两种子网掩码

子网掩码是“255.255.255.0”的网络:

最后面一个数字可以在0~255范围内任意变化,因此可以提供256个 IP 地址。

但是实际可用的 IP 地址数量是256-2,即254个,因为主机号不能全是“0”或全是“1”。

主机号全为0,表示网络号主机号全为1,表示网络广播注意:

如果将子网掩码设置过大,也就是说子网范围扩大,那么,根据子网寻径规则,很可能发往和本地主机不在同一子网内的目标主机的数据,会因为错误的判断而认为目标主机是在同一子网内,那么,数据包将在本子网内循环,直到超时并抛弃,使数据不能正确到达目标主机,导致网络传输错误;如果将子网掩码设置得过小,那么就会将本来属于同一子网内的机器之间的通信当做是跨子网传输,数据包都交给缺省网关处理,这样势必增加缺省网关(文章下方有解释)的负担,造成网络效率下降。因此,子网掩码应该根据网络的规模进行设置。如果一个网络的规模不超过254台电脑,采用“255.255.255.0”作为子网掩码就可以了,现在大多数局域网都不会超过这个数字,因此“255.255.255.0”是常用的 IP 地址子网掩码;假如在一所大学具有1500多台电脑,这种规模的局域网可以使用“255.255.0.0”。

TCP 与 UDP 协议

在 TCP/IP 网络体系结构中,TCP(传输控制协议)、UDP(用户数据报协议)是传输层重要的两种协议,为上层用户提供级别的通信可靠性。

传输控制协议(TCP):TCP(传输控制协议)定义了两台计算机之间进行可靠的传输而交换的数据和确认信息的格式 以及计算机为了确保数据的正确到达而采取的措施。协议规定了TCP软件怎样识别给定计算机上的多个目的进程如何对分组、重复这类差错进行恢复。协议还规定了两台计算机如何初始化一个 TCP 数据流传输以及如何结束这一传输。TCP 最大的特点就是提供的是面向连接、可靠的字节流服务。

用户数据报协议(UDP):UDP(用户数据报协议)是一个简单的面向数据报的传输层协议。提供的是非面向连接的、 不可靠的数据流传输。UDP 不提供可靠性,也不提供报文到达确认、排序以及流量控制等功能。它只是把应用程序传给 IP 层的数据发送出去,但是并不能保证它们能到达目的地。因此报文可能会丢失、重复以及乱序等。但由于 UDP 在传输数据报文前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。

TCP 和 UDP 最大的区别就是:TCP 是面向连接的,UDP 是无连接的。TCP 协议和 UDP 协议各有所长、各有所短,适用于不同要求的通信环境

面向连接的 TCP:TCP 协议是一种可靠的、一对一的、面向有连接的通信协议

“面向连接”就是在正式通信前必须要与对方建立起连接,是按照电话系统建模的。比如你给别人打电话,必须等线路接 通了、对方拿起话筒才能相互通话。客户端与服务端在使用 TCP 传输协议时要先建立一个“通道”,在传输完毕之后又要关闭这“通道”,前者可以被形象地成为“三次握手”,而后者则可以被称为“四次挥手”。

通道的建立——三次握手:

在建立通道时,客户端首先要向服务端发送一个 SYN 同步信号。

服务端在接收到这个信号之后会向客户端发出 SYN 同步信号和 ACK 确认信号。

当服务端的 ACK 和 SYN 到达客户端后,客户端与服务端之间的这个“通道”就会被建立起来。

通道的关闭——四次挥手:

在数据传输完毕之后,客户端会向服务端发出一个 FIN 终止信号。

服务端在收到这个信号之后会向客户端发出一个 ACK 确认信号。

如果服务端此后也没有数据发给客户端时服务端会向客户端发送一个 FIN 终止信号。

客户端收到这个信号之后会回复一个确认信号,在服务端接收到这个信号后,服务端与客户端的通道也就关闭。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Wfx5gVU-1644045923261)(https://s2.loli.net/2022/02/02/Lw4apNAd81cYlM3.jpg)]

TCP 协议能为应用程序提供可靠的通 信连接,使一台计算机发出的字节流无差错地发往网络上的其他计算机,对可靠 性要求高的数据通信系统往往使用 TCP 协议传输数据。

无连接的 UDP 协议:UDP 协议是一种不可靠的、面向无连接、可以实现多对一、一对多和一对一连接的通信协议

“无连接”就是在正式通信前不必与对方先建立连接,不管对方状态就直接发送。与手机短信非常相似:你在发短信的时 候,只需要输入对方手机号就 OK 了。UDP 在传输数据前既不需要建立通道,在数据传输完毕后也不需要将通道关闭。只要 客户端给服务端发送一个请求,服务端就会一次性地把所有数据发送完毕。UDP 在传输数据时不会对数据的完整性进行验 证,在数据丢失或数据出错时也不会要求重新传输,因此也节省了很多用于验证数据包的时间,所以以 UDP 建立的连接的延迟会比以 TCP 建立的连接的延迟更低。UDP 不会根据当前的网络情况来控制数据的发送速度,因此无论网络情况是好是坏,服务端都会以恒定的速率发送数据。虽然这样有时会造成数据的丢失与损坏,但是这一点对于一些实时应用来说是十分重要的。基于以上三点,UDP 在数据传输方面速度更快,延迟更低,实时性更好,因此被广泛地用于通信领域和视频网站当中

UDP 适用于一次只传送少量数据、对可靠性要求不高的应用环境。比如,我们经常使用 “ping” 命令来测试两台主机之间 TCP/IP 通信是否正常,其实 “ping” 命令的原理就是向对方主机发送 ICMP 数据包,然后对方主机确认收到数据包,如果数据 包到达的消息及时反馈回来,那么网络就是通的。例如,在默认状态下,一次 “ping” 操作发送4个数据包。大家可以看到,发送的数据包数量是4包,收到的也是4包(因为对方主机收到后会发回一个确认收到的数据包)。这充分说明了 UDP 协议是面向非连接的协议,没有建立连接的过程。正因为 UDP 协议没有连接的过程,所以它的通信效率高;但也正因为如 此,它的可靠性不如 TCP 协议高。QQ 就使用 UDP 发消息,因此有时会出现收不到消息的情况。

HTTP 协议

HTTP 是一个简单的请求-响应协议,它通常运行在 TCP 之上。它指定了客户端可能发送给服务器什么样的消息以及得到 什么样的响应。请求和响应消息的头以 ASCII 码形式给出;而消息内容则具有一个类似 MIME 的格式。这个简单模型是早期 Web 成功的有功之臣,因为它使得开发和部署是那么的直截了当。

HTTP 是基于客户/服务器模式,且面向连接的。典型的 HTTP 事务处理有如下的过程

客户与服务器建立连接;

客户向服务器提出请求;

服务器接受请求,并根据请求返回相应的文件作为应答;

客户与服务器关闭连接。

客户与服务器之间的 HTTP 连接是一种一次性连接,它限制每次连接只处理一个请求,当服务器返回本次请求的应答后便立即关闭连接,下次请求再重新建立连接。这种一次性连接主要考虑到 WWW 服务器面向的是 Internet 中成干上万个用户, 且只能提供有限个连接,故服务器不会让一个连接处于等待状态,及时地释放连接可以大大提高服务器的执行效率。

HTTP 是一种无状态协议,即服务器不保留与客户交易时的任何状态。这就大大减轻了服务器记忆负担,从而保持较快的响应速度。HTTP 是一种面向对象的协议。允许传送任意类型的数据对象。它通过数据类型和长度来标识所传送的数据内容和大小,并允许对数据进行压缩传送。当用户在一个 HTML 文档中定义了一个超文本链后,浏览器将通过 TCP/IP 协议与指定的服务器建立连接。

从技术上讲是客户在一个特定的 TCP 端口(端口号一般为80)上打开一个套接字。如果服务器一直在这个周知的端口上倾听连接,则该连接便会建立起来。然后客户通过该连接发送一个包含请求方法的请求块。

HTTP 规范定义了9种请求方法,每种请求方法规定了客户和服务器之间不同的信息交换方式,常用的请求方法是

GET 和 POST。服务器将根据客户请求完成相应操作,并以应答块形式返回给客户, 后关闭连接。

端口

什么是端口?如下图:

端口就是:是设备与外界通讯交流的出口那么 TCP/IP 协议中的端口指的是什么呢?

端口就好一个房子的门,是出入这间房子的必经之路。如果一个进程需要收发网络数据,那么就需要有这样的端口,在 Linux 系统中,端口可以有65536(2的16次方)个之多!既然有这么多,操作系统为了统一管理,所以进行了编号,这就是端口号

端口是通过端口号来标记的,端口号只有整数,范围是从0到65535

端口号不是随意使用的,而是按照一定的规定进行分配。

端口的分类标准有好几种,我们这里不做详细讲解,只介绍一下知名端口和动态端口知名端口是众所周知的端口号,范围从0到1023

80 端口分配给 HTTP 服务
21 端口分配给 FTP 服务

可以理解为,一些常用的功能使用的号码是估计的,好比 电话号码110、10086、10010一样,一般情况下,如果一个程序需要使用知名端口的需要有 root 权限

动态端口的范围是从1024到65535,之所以称为动态端口,是因为它一般不固定分配某种服务,而是动态分配。动态分配是指当一个系统进程或应用程序进程需要网络通信时,它向主机申请一个端口,主机从可用的端口号中分配一个供它使用。当这个进程关闭时,同时也就释放了所占用的端口号。

# 用 "netstat -an" 查看端口状态

端口有什么用呢 ? 我们知道,一台拥有IP地址的主机可以提供许多服务,比如 HTTP(万维网服务)、FTP(文件传输)、SMTP(电子邮件)等,这些服务完全可以通过1个 IP 地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠 IP 地址,因为 IP 地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同的服务的。 需要注意的是,端口并不是一一对应的。比如你的电脑作为客户机访问一台 WWW 服务器时,WWW 服务器使用“80”端口与你的电脑通信,但你的电脑则可能使用“3457”这样的端口。

BS/CS 结构

C/S 是 Client/Server 的缩写。服务器通常采用高性能的PC、工作站或小型机,并采用大型数据库系统,如Oracle、Sybase、Informix 或 SQL Server。客户端需要安装专用的客户端软件。

B/S 是 Browser/Server 的缩写,客户机上只要安装一个浏览器(Browser),如 Netscape Navigator 或 Internet Explorer,服务器安装 Oracle、Sybase、Informix 或 SQL Server 等数据库。在这种结构下,用户界面完全通过

WWW 浏览器实现,一部分事务逻辑在前端实现,但是主要事务逻辑在服务器端实现。浏览器通过 Web Server 同数据库进行数据交互。

系统开发中 C/S 结构(Client/Server)中 Client(客户端)往往可以由 B/S 结构(Browser/Server结构)的 Browser(浏览器)及其载体承担,C/S 结构的 Web 应用与 B/S 结构(Browser/Server结构)具有紧密联系。大系统

和复杂系统中,C/S 结构和 B/S 结构的嵌套也很普遍。 原来的 Client/Server 结构转变成 Browser/Server 结构后,客户机的压力大大减轻,负荷被均衡地分配给了服务器。由于这种结构不再需要专用的客户端软件,因此也使技术维护人员从繁重的安装、配置和升级等维护工作中解脱了出来,可以把主要精力放在服务器程序的更新工作上。同时,使用 Web 浏览器作为客户端软件,界面友好,新开发的系统也不需要用户每次都从头学习。

Socket

我们了解了协议的基本概念,协议之间的关系,与层级之间的关联,完成了对网络的一个理解,当我们在 QQ、微信给别人发送消息时,就是通过这些层级数据传输的协议去传输我们的内容,或是我们浏览网页,打开一个百度页面,都是基于协议传输的数据显示请求的页面,那我们如何去实现这些?不可能每一步都需要去写,从 底层开始写起,那就太麻烦了,由此引出一个概念 Socket,需要一一解答的问题,Socket 在哪里?Socket 是什么?目的是为了做什么?先看下图

Socket 也叫套接字(Socket)随着 TCP/IP 协议的使用,也越来越多地被使用在网络应用程序的构建中。实际上,Socket 编程也已经成为网络中传送和接收数据的首选方法。套接字早是由伯克利在 BSD 中推出的一种进程间通信方案和网络互联的基本机制。现在,已经有多种相关的套接字实现,但是大部分还是遵循着初的设计要求。套接字相当于应用程序访问下层网络服务的接口。使用套接字,可以使得不同的主机之间进行通信,从而实现数据交换。

Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket 其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Socket 接口后面,对用户来说,一组简单的接口就是全部,让 Socket 去组织数据,以符合指定的协议。

Socket

本地的进程间通信(IPC)有很多种方式,例如

队列

同步(互斥锁、条件变量等)

以上通信方式都是在一台机器上不同进程之间的通信方式,那么问题来了

网络中进程之间如何通信

首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!

在本地可以通过进程 PID 来唯一标识一个进程,但是在网络中这是行不通的。

其实 TCP/IP 协议族已经帮我们解决了这个问题,网络层的“ip 地址”可以唯一标识网络中的主机,而传输层的“协议 + 端口”可以唯一标识主机中的应用程序(进程)。

这样利用 ip 地址,协议,端口就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互

socket (简称 套接字) 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页、QQ 聊天、收发 email 等等

Socket编程

那我们如何实现尼?

在 Python 中 使用 socket 模块的函数 socket 就可以完成:

socket.socket(AddressFamily, Type)

说明:

套接字最初是为同一主机上的应用程序所创建,使得主机上运行的一个程序(又名一个进程)与另一个运行的程序进行通信。这就是所谓的进程间通信(Inter Process Communication,IPC)有两种类型的套接字:基于文件的和面向网络的。

'''
  函数 socket.socket 创建一个 socket,返回该 socket 的描述符,该函数带有两个参数:
  - Address Family:可以选择 AF_INET(用于 Internet 进程间通信) 或者 AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET
  - Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)
'''

那我们来创建一个基于 tcp socket 的套接字

import socket
# 获得socket对象 AF_INET表示基于网络的套接字
# SOCK_STREAM表示的是TCP协议
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print ('Socket Created')

创建一个udp socket(udp 套接字)

import socket
# 获得socket对象 AF_INET表示基于网络的套接字
# SOCK_DGRAM表示的是UDP协议
socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print ('Socket Created')

以上就是基于 socket 模块实现创建最简单的对象模式,那我们来基于 socket 实现 TCP/UDP 的实现

UDP 客户端

# -*- coding: UTF-8 -*-
# 文件名:client.py
# 导入 socket 模块
from socket import *
# 创建套接字
client_socket = socket(AF_INET, SOCK_DGRAM)
# 准备接收方地址
server_host_post = ('127.0.0.1', 8080)
# 发送数据时,python3需要将字符串转成byte
# encode(‘utf-8’)# 用utf-8对数据进行编码,获得bytes类型对象
client_data = input("请输入:").encode('utf8')
# 将拿到转为bytes类型data数据对象,通过socket中的sendto方法,将数据发送到ip+协议+端口对应的地址
client_socket.sendto(client_data, server_host_post)
# 如果发送成功我们就提示一句发送成功
print('发送成功')
# 关闭客户端
client_socket.close()

以上就是基于 socket 模块实现创建最简单的对象模式,那我们来基于 socket 实现 TCP/UDP 的实现

UDP 客户端

# -*- coding: UTF-8 -*-
# 文件名:client.py
# 导入 socket 模块
from socket import *
# 创建套接字
client_socket = socket(AF_INET, SOCK_DGRAM)
# 准备接收方地址
server_host_post = ('127.0.0.1', 8080)
# 发送数据时,python3需要将字符串转成byte
# encode(‘utf-8’)# 用utf-8对数据进行编码,获得bytes类型对象
client_data = input("请输入:").encode('utf8')
# 将拿到转为bytes类型data数据对象,通过socket中的sendto方法,将数据发送到ip+协议+端口对应的地址
client_socket.sendto(client_data, server_host_post)
# 如果发送成功我们就提示一句发送成功
print('发送成功')
# 关闭客户端
client_socket.close()

我们看到运行结果是输入我们想要的内容是能运行成功的,但是我们内容去了那里了,这里我们就需要详细的了解协议的性质,是无连接的,既不能保证数据的完整性,也不能保证数据发送,所以就无法产生稳定的数据传输,但

是也是可以接收到消息的哦,这里就需要我们的服务器,任何客户端,必须得链接到其他的服务器,进行交互响应,才能完成动态的信息交互,那我们怎么实现呢?

SocketServer

我们在上一章讲到简单的 Socket 的编程实现操作,那我们现在来完成基于服务器与客户端的协议之间交互信息

UDP

UDP — 用户数据报协议,是一个无连接的简单的面向数据报的运输层协议。UDP 不提供可靠性,它只是把应用程序传给 IP 层的数据报发送出去,但是并不能保证它们能到达目的地。由于 UDP 在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。

UDP 是一种面向无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

UDP 特点:

UDP 是面向无连接的通讯协议,UDP 数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送

UDP 传输数据时有大小限制,每个被传输的数据报必须限定在 64 KB 之内。

UDP 是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。

【适用情况】

UDP 是面向消息的协议,通信时不需要建立连接,数据的传输自然是不可靠的,UDP 一般用于多点通信和实时的数据业务,比如

语音广播

视频

QQ

TFTP(简单文件传送)

SNMP(简单网络管理协议)

RIP(路由信息协议,如报告股票市场,航空信息)

DNS(域名解释)

相比较于 TCP 注重速度流畅

UDP 操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中 client/server 应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用 UDP 会更合理一些。

那如何实现尼?

我们创建一个 udp 客户端程序的流程是简单的,具体步骤如下:

'''
  1.创建客户端套接字
  2.发送/接收数据
  3.关闭套接字
'''

打开我们的开发工具编译器

客户端如下代码:发送数据

# -*- coding: UTF-8 -*-
# 文件名:client.py
# 导入 socket 模块
from socket import *
# 创建套接字
client_socket = socket(AF_INET, SOCK_DGRAM)
# 准备接收方地址
server_host_post = ('127.0.0.1', 8080)
# 发送数据时,python3需要将字符串转成byte
# encode(‘utf-8’)# 用utf-8对数据进行编码,获得bytes类型对象
client_data = input("请输入:").encode('utf8')
# 将拿到转为bytes类型data数据对象,通过socket中的sendto方法,将数据发送到ip+协议+端口对应的地址
client_socket.sendto(client_data, server_host_post)
# 如果发送成功我们就提示一句发送成功
print('发送成功')
# 关闭客户端
client_socket.close()

客户端的结构

使用 socket(),生成套接字描述符

通过 host_post 结构设置服务器地址和监听端口

向服务器发送数据,sendto()

关闭套接字,close()

运行看看

通过客户端发送成功,我们指定了端口,但是我们没有与服务器建立连接,没有确定8080端口的连接对象,可以将 ip 地址与端口随意需改符合要求的范围,都可以将数据正常发送

此时数据发送,这里就体现 UDP 数据的特性,面向无连接的通讯协议这里我们接受数据该如何实现尼?往下看服务器端如下代码:接收数据

# -*- coding: UTF-8 -*-
# 文件名:server.py
# 导入 socket 模块
from socket import *
# 创建套接字对象
socket = socket(AF_INET, SOCK_DGRAM)
# 准备接收地址
host_post = ('127.0.0.1', 8080)
# 绑定地址、端口,类型为元组
socket.bind(host_post)
# 这里接受到的数据socket.recvfrom(1024)是一个元组形式
# 那这里可以看看具体的信息
data = socket.recvfrom(1024)
print(data)
print(data[0].decode('utf8'))
# 关闭连接
socket.close()

服务器端的结构

使用函数 socket(),生成套接字描述符;

通过 host_post 结构设置服务器地址和监听端口;

使用 bind() 函数绑定监听端口,将套接字文件描述符和地址类型变量(host_post)进行绑定;

接收客户端的数据,使用 recvfrom() 函数接收客户端的网络数据;

关闭套接字,使用 close() 函数释放资源;

那让我们来看一下运行的效果与结果

先运行我们的服务器,再运行我们的客户端,输入我们需要给到服务器的数据,在客户端,观察发现向服务器发送消息的时候没有给客户端绑定端口?原来操作系统在此 做了些隐蔽的事情,当 socket 首先向服务器发消息时客户端自动选折 IP 和一个 PORT 与该 socket 关联了起来。

那客户端与服务器之间的交互,能不能绑定端口,更多是多人交互尼,来我们继续往下走

echo 服务的应用 ,echo 服务是一种非常有用的用于调试和检测的工具。该协议接收到什么原样发回,类似于日常生活中的“回声”,即存在回显

我们修改服务器与客户端的代码

客户端代码如下:

# -*- coding: UTF-8 -*-
# 文件名:client.py
import socket
# 创建套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
    # 准备接收方地址
    server_host_post = ('127.0.0.1', 12345)
    # 发送数据时,python3需要将字符串转成byte
    # encode(‘utf-8’)# 用utf-8对数据进行编码,获得bytes类型对象
    client_data = input("请输入:").encode('utf8')
    # 将拿到转为bytes类型data数据对象,通过socket中的sendto方法,将数据发送到ip+协议+端口对应的地址
    client_socket.sendto(client_data, server_host_post)
    # 这里接受到的数据socket.recvfrom(1024)是一个元组形式,接受服务器返回来的信息
    print('返回数据是:', client_socket.recvfrom(1024)[0].decode('utf8'))
# 关闭客户端
client_socket.close()

服务器代码如下:

# -*- coding: UTF-8 -*-
# 文件名:client.py
import socket
# 创建套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
    # 准备接收方地址
    server_host_post = ('127.0.0.1', 12345)
    # 发送数据时,python3需要将字符串转成byte
    # encode(‘utf-8’)# 用utf-8对数据进行编码,获得bytes类型对象
    client_data = input("请输入:").encode('utf8')
    # 将拿到转为bytes类型data数据对象,通过socket中的sendto方法,将数据发送到ip+协议+端口对应的地址
    client_socket.sendto(client_data, server_host_post)
    # 这里接受到的数据socket.recvfrom(1024)是一个元组形式,接受服务器返回来的信息
    print('返回数据是:', client_socket.recvfrom(1024)[0].decode('utf8'))
# 关闭客户端
client_socket.close()

再次来看运行结果

没有给客户端指定唯一的端口与 ip 地址,而是通过服务器端口进行传输返回数据,此时如果我在加入新的客户端,是否就可以完成多人聊天室的功能,UDP 的广播形式,再看,我将复制一个客户端文件,命名为 client1,现在将使用两个客户端对服务器进行发送消息

udp是TCP/IP协议族中的一种协议能够完成不同机器上的程序间的数据通信

udp的服务器和客户端的区分:往往是通过请求服务和提供服务来进行区分

请求服务的一方称为:客户端

提供服务的一方称为:服务器

一般情况下,服务器端,需要绑定端口,目的是为了让其他的客户端能够正确发送到此进程客户端,一般不需要绑定,而是让操作系统随机分配,这样就不会因为需要绑定的端口被占用而导致程序无法运行的情况

TFTP

TFTP(Trivial File Transfer Protocol,简单文件传输协议)是 TCP/IP 协议族中的一个用来在客户端与服务器之间进行简单文件传输的协议

特点:

简单

占用资源小

适合传递小文件

适合在局域网进行传递

端口号为69

基于UDP实现

TFTP 服务器默认监听69号端口

当客户端发送“下载”请求(即读请求)时,需要向服务器的69端口发送

服务器若批准此请求,则使用一个新的、临时的端口进行数据传输

当服务器找到需要现在的文件后,会立刻打开文件,把文件中的数据通过 TFTP 协议发送给客户端

如果文件的总大小较大(比如3M),那么服务器分多次发送,每次会从文件中读取512个字节的数据发送过来

因为发送的次数有可能会很多,所以为了让客户端对接收到的数据进行排序,在服务器发送那512个字节数据的时候,会多发2个字节的数据,用来存放序号,并且放在512个字节数据的前面,序号是从1开始的

因为需要从服务器上下载文件时,文件可能不存在,那么此时服务器就会发送一个错误的信息过来,为了区分服务发送的是文件内容还是错误的提示信息,又用了2个字节来表示这个数据包的功能(称为操作码),并且在序号的前面

image.png

因为 udp 的数据包不安全,即发送方发送是否成功不能确定,所以 TFTP 协议中规定,为了让服务器知道客户端已经接收到了刚刚发送的那个数据包,所以当客户端接收到一个数据包的时候需要向服务器进行发送确认信息,即发送收到了,这样的包成为 ACK (应答包)

为了标记数据已经发送完毕,所以规定,当客户端接收到的数据小于516(2字节操作码 + 2个字节的序号 + 512字节数据)时,就意味着服务器发送完毕了,TFTP 数据包的格式如下:

那既然是基于 UDP 实现的代码,那我们来看是如何实现的服务器端代码:

服务器代码:

# -*- coding: UTF-8 -*-
# 文件名:TFTP_server.py
from socket import *
import struct
def download(filename, user_ip, user_port):
    socket_down = socket(AF_INET, SOCK_DGRAM)
    num = 0
    try:
        f = open(filename, 'rb')
    except:
        error_data = struct.pack('!HHHb', 5, 5, 5, num)
        socket_down.sendto(error_data, (user_ip, user_port))  # 文件不存在时发送
        exit()  # 只会退出此线程
        while True:
            read_data = f.read(512)
            send_data = struct.pack('!HH', 3, num) + read_data
            socket_down.sendto(send_data, (user_ip, user_port))  # 数据第一次发送
            if len(read_data) < 512:
                print('传输完成, 对方下载成功')
                exit()
            recv_ack = socket_down.recv(1024)  # 第二次接收
            caozuoma, ack_num = struct.unpack("!HH", recv_ack)
            #    print(caozuoma,ack_num,len(read_data))
            num += 1
            if int(caozuoma) != 4 or int(ack_num) != num - 1:
                exit()
  f.close()
s = socket(AF_INET, SOCK_DGRAM)
s.bind(('', 69))
def main():
    while 1:
        recv_data, (user_ip, user_port) = s.recvfrom(1024)  # 第一次客户连接69端口
        print(recv_data, user_ip, user_port)
        if struct.unpack('!b5sb', recv_data[-7:]) == (0, b'octet', 0):
            caozuoma = struct.unpack('!H', recv_data[:2])
            filename = recv_data[2:-7].decode('gb2312')
            if caozuoma[0] == 1:
                print('对方想下载数据', filename)
                download(filename, user_ip, user_port)
if __name__ == '__main__':
     main()

Python 中的 struct 主要是用来处理 C 结构数据的,在转化过程中,在转化过程中,主要用到了一个格式化字符串

(format strings),用来规定转化的方法和格式。比如代码中的:’!H’

客户端代码:

# coding=utf-8
# 文件名:tftp_client.py
import struct
from socket import *
filename = 'test.jpg'
server_ip = '127.0.0.1'
send_data = struct.pack('!H%dsb5sb' % len(filename), 1, filename.encode('gb2312'), 0,
                        'octet'.encode('gb2312'), 0)
tftp_client = socket(AF_INET, SOCK_DGRAM)
# 第一次发送, 连接服务器69端口
tftp_client.sendto(send_data, (server_ip, 69))
# 打开二进制文件,追加写如文件
f = open(filename, 'ab')
while 1:
    # 接收数据
    recv_data = tftp_client.recvfrom(1024)
    # 获取数据块编号
    caozuoma, ack_num = struct.unpack('!HH', recv_data[0][:4])
    rand_port = recv_data[1][1]  # 获取服务器的随机端口
    if int(caozuoma) == 5:
        print('服务器返回: 文件不存在...')
        break
    print(caozuoma, ack_num, rand_port, len(recv_data[0]))
    f.write(recv_data[0][4:])
    if len(recv_data[0]) < 516:
        break
    ack_data = struct.pack("!HH", 4, ack_num)
    # 回复ACK确认包
    tftp_client.sendto(ack_data, (server_ip, rand_port))

运行结果如下

看到原本本地的数据是没有的,当然实际上我们就是从本地凭空生成或者是读取一个 TFTP 的文件,当我们通过此方式,将数据进行连接传输,那我们就能完成使用对 TFTP 协议的使用和交互数据,这里我们理解了关于基于 UDP 模式下的多用户模式的或者是高速率信息传输,但不保证数据的完整性,那我们在需要准确数据保证数据不会丢失的情况该怎么办尼?例如发送或者接受邮件,例如资料文件等传输,我们需要准确的数据信息,基于 TCP 的面向连接。

TCP

传输控制协议(TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,也是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。

例如生活中的电话机,我想让别人能更够打通我的电话交流或者完成工作等等事务前,我还得需要做以下几件事情:

买个手机

插上手机卡

设计手机为正常接听状态(即能够响铃)

静静的等着别人拨打

如同上面的电话机过程一样,在程序中,如果想要完成一个 tcp 服务器的功能,需要的流程如下:

socket 创建一个套接字

bind 绑定 ip 和 port

listen 使套接字变为可以被动链接

accept 等待客户端的链接

recv/send 接收发送数据

由此一个很简单的 tcp 服务器如下:

# coding=utf-8
# 文件名:tcp_server.py
from socket import *
# 创建socket
# SOCK_STREAM基于TCP
tcp_Socket = socket(AF_INET, SOCK_STREAM)
# 绑定本地信息
# ip地址和端口号,ip一般不用写,表示本机的任何一个ip
host_port = ('', 12345)
tcp_Socket.bind(host_port)
# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了
tcp_Socket.listen(5)
# 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务器
# newSocket用来为这个客户端服务
# tcp_Socket就可以省下来专门等待其他新客户端的链接
newSocket, clientAddr = tcp_Socket.accept()
# 接收对方发送过来的数据,最大接收1024个字节
recvData = newSocket.recv(1024)
print('接收到的数据为:', recvData.decode('utf8'))
# 发送一些数据到客户端
senData = "thank you !"
newSocket.send(senData.encode('utf8'))
# 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接
newSocket.close()
# 关闭监听套接字,只要这个套接字关闭了,就意味着整个程序不能再接收任何新的客户端的连接
tcp_Socket.close()

由此我们的客户端创建好了。

客户端代码如下

# coding=utf-8
# 文件名:tcp_client.py
# 创建socket
tcp_client = socket(AF_INET, SOCK_STREAM)
# 链接服务器
host_port = ('127.0.0.1', 12345)
tcp_client.connect(host_port)
# 提示用户输入数据
sendData = input("请输入要发送的数据:")
# 发送数据给指定的客户端
tcp_client.send(sendData.encode('utf8'))
# 接收对方发送过来的数据,最大接收1024个字节
recvData = tcp_client.recv(1024)
print('接收到的数据为:', recvData.decode('utf8'))
# 关闭套接字
tcp_client.close()

我们先来看看运行后的结果

在我们的服务器端,我们绑定 IP + 端口协议方式,将服务器的数据传输方式绑定,基于数据传输,返回指定数据连接服务器的信息,在这里面我们完成了对数据基于 tcp 的传输流程方式,当客户端需要链接服务器时,就需要使用 connect 进行链接,udp 是不需要链接的而是直接发送,但是 tcp 必须先链接,只有链接成功才能通信

tcp 注意点

tcp 服务器一般情况下都需要绑定,否则客户端找不到这个服务器

tcp 客户端一般不绑定,因为是主动链接服务器,所以只要确定好服务器的 ip、port 等信息就好,本地客户端可以随机

tcp 服务器中通过 listen 可以将 socket 创建出来的主动套接字变为被动的,这是做 tcp 服务器时必须要做的

当一个 tcp 客户端连接服务器时,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务

listen 后的套接字是被动套接字,用来接收新的客户端的链接请求的,而 accept 返回的新套接字是标记这个新客户端的

关闭 listen 后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信。

关闭 accept 返回的套接字意味着这个客户端已经服务完毕

当客户端的套接字调用 close 后,服务器端会 recv 解堵塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线

那我们就可以来了解一下如何实现模拟QQ的聊天

模拟QQ的聊天

服务器代码

# coding=utf-8
# 文件名:qq_server.py
from socket import *
# 创建socket
tcp_server = socket(AF_INET, SOCK_STREAM)
# 绑定本地信息
host_port = ('', 12345)
tcp_server.bind(host_port)
# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了
tcp_server.listen(5)
while True:
    # 如果有新的客户端来链接服务器,那么就产生一个信心的套接字专门为这个客户端服务器
    # newSocket用来为这个客户端服务
    # tcpSerSocket就可以省下来专门等待其他新客户端的链接
    newSocket, host_port = tcp_server.accept()
    while True:
        # 接收对方发送过来的数据,最大接收1024个字节
        recvData = newSocket.recv(1024)
        # 如果接收的数据的长度为0,则意味着客户端关闭了链接
        if len(recvData) > 0:
            print('recv:', recvData)
        else:
            break
        # 发送一些数据到客户端
        sendData = input("send:")
        newSocket.send(sendData.encode('utf8'))
# 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接
newSocket.close()
# 关闭监听套接字,只要这个套接字关闭了,就意味着整个程序不能再接收任何新的客户端的连接
tcp_server.close()

客户端代码如下:

# coding=utf-8
# 文件名:qq_server.py
from socket import *
# 创建socket
tcp_client = socket(AF_INET, SOCK_STREAM)
# 链接服务器
host_port = ('127.0.0.1', 12345)
tcp_client.connect(host_port)
while True:
    # 提示用户输入数据
    sendData = input("send:")
    if len(sendData) > 0:
        tcp_client.send(sendData.encode('utf8'))
    else:
        break
    # 接收对方发送过来的数据,最大接收1024个字节
    recvData = tcp_client.recv(1024)
    print('recv:', recvData.decode('uft8'))
# 关闭套接字
tcp_client.close()

好我们直接来看看运行的结果

以上我们完成了简易的QQ通信功能,通信双方必须先建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输。双方间的数据传输都可以通过这一个连接进行。完成数据交换后,双方必须断开此连接,以释放系统资源。这种连接是一对一的。

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
目录
相关文章
|
16天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
16天前
|
程序员 开发者 Python
Python网络编程基础(Socket编程) 错误处理和异常处理的最佳实践
【4月更文挑战第11天】在网络编程中,错误处理和异常管理不仅是为了程序的健壮性,也是为了提供清晰的用户反馈以及优雅的故障恢复。在前面的章节中,我们讨论了如何使用`try-except`语句来处理网络错误。现在,我们将深入探讨错误处理和异常处理的最佳实践。
|
3天前
|
机器学习/深度学习 算法 算法框架/工具
数据分享|PYTHON用KERAS的LSTM神经网络进行时间序列预测天然气价格例子
数据分享|PYTHON用KERAS的LSTM神经网络进行时间序列预测天然气价格例子
24 0
|
15小时前
|
机器学习/深度学习 算法 算法框架/工具
PYTHON用KERAS的LSTM神经网络进行时间序列预测天然气价格例子
PYTHON用KERAS的LSTM神经网络进行时间序列预测天然气价格例子
|
1天前
|
机器学习/深度学习 存储 监控
数据分享|Python卷积神经网络CNN身份识别图像处理在疫情防控下口罩识别、人脸识别
数据分享|Python卷积神经网络CNN身份识别图像处理在疫情防控下口罩识别、人脸识别
10 0
|
3天前
|
存储 网络协议 关系型数据库
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
|
3天前
|
机器学习/深度学习 算法 Python
Python用RNN神经网络:LSTM、GRU、回归和ARIMA对COVID19新冠疫情人数时间序列预测
Python用RNN神经网络:LSTM、GRU、回归和ARIMA对COVID19新冠疫情人数时间序列预测
47 12
|
8天前
|
机器学习/深度学习 Python
Python用LSTM长短期记忆神经网络对不稳定降雨量时间序列进行预测分析
Python用LSTM长短期记忆神经网络对不稳定降雨量时间序列进行预测分析
19 0
|
8天前
|
JSON 网络协议 API
Python网络编程面试题精讲
【4月更文挑战第15天】本文介绍了Python网络编程的面试重点,包括基础Socket编程、HTTP协议与requests库、异步编程与asyncio库。通过实例解析常见面试题,强调了非阻塞套接字、异常处理、HTTP状态码检查以及异步任务管理等关键点。提供代码示例帮助读者巩固概念,助力面试准备。
16 0
|
10天前
|
机器学习/深度学习 存储 测试技术
使用PYTHON中KERAS的LSTM递归神经网络进行时间序列预测
使用PYTHON中KERAS的LSTM递归神经网络进行时间序列预测
19 0