热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python高级之网络编程及TCP/IP协议簇的OSI七层模型介绍

本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。

本节内容

  1. 网络通信概念
  2. socket编程
  3. socket模块一些方法
  4. 聊天socket实现
  5. 远程执行命令及上传文件
  6. socketserver及其源码分析

1.网络通信概念

说到网络通信,那就不得不说TCP/IP协议簇的OSI七层模型了,这个东西当初在学校都学烂了。。。(PS:毕竟本人是网络工程专业出身。。。) 简单介绍下七层模型从底层到上层的顺序:物理层(定义物理设备的各项标准),数据链路层(mac地址等其他东西的封装),网络层(IP包头的的封装),传输层(TCP/UDP数据报头的封装),会话层(这一层涉及的东西不多,但是我觉得SSL(安全套接字)应该封装在这一层,对于应用是透明的),表示层(数据的压缩解压缩放在这一层),应用层(这一层就是用户使用的应用了)

OSI的七层模型从上到下是一层一层封装的过程,一个数据从一台计算机到另一台计算机是先从上到下封装,之后传输到达另一台计算机之后是从下到上一层一层解封装的过程。

好了,说了这么多,那么我们开发里面涉及到的网络通信包含一些什么东西呢?首先我们程序开发中大部分所使用的协议是TCP协议(传输层)UDP协议涉及的比较少。网络层是IPV4协议,当然IPV6可能是未来的主流,还有一些其他网络协议这里并不涉及。。。SSL(安全套接字)可能在web应用中为了提供数据安全性用得比较多,但是服务端应用程序和程序之间的数据传输不会使用到ssl进行数据安全性的保护。所以,我们平常用的基于网络编程所使用的网络协议一般就是使用传输层的TCP协议,网络层的IPV4协议,更底层的协议。。。并不需要我们考虑,那些是网络设备之间该关心的事情。。。哈哈哈

那么,为什么要用TCP协议呢?因为TCP协议提供了一个面向连接的,稳定的通道,数据是按照顺序到达的,TCP协议的机制保证了TCP协议传输数据是一个可靠的传输。但是TCP协议也有他的缺点,那就是保证可靠传输所牺牲的代价就是速度比较慢(当然也不是很离谱,除非在某些极端情况下:比如传输大量的小数据)TCP之所以是面向连接的是因为它的三次握手以及四次挥手(太出名了,这里不用介绍了。。。),保障数据包按照顺序到达是通过分片编号实现的,每一个数据包都有一个编号,接收端根据这个编号去将接收的数据按原来数据顺序组装起来。当然,TCP协议之所以是一个可靠的传输和他的重传机制也是分不开的,当对方没有收到你发送的一个数据包的时候,TCP协议会重新传输这个数据包到对方,直到对方确认收到了这个数据包为止。。。。当然TCP协议里面还有很多优秀的东西。这里就不一一赘述了。哈哈,不然这里就成了网络专场了。。。

好了,现在确定了我们使用TCP/IP来进行网络通信,那么要实现通信需要知道对方机器的IP地址和端口号(当然,这里指的端口号一般是指TCP的端口号,从1-65535,其中,1024及之前的端口被定义为知名端口,最好不要使用)

2.socket编程

前面的第一节只是前戏,为了引出我们今天介绍的socket编程,这前戏做的也是挺累的,哈哈哈。

python中的socket是一个模块,使用这个内置模块能够让我们实现网络通信。其实在unix/linux一切皆文件的思想下,socket也可以看作是一个文件。。。python进行网络数据通信也可以理解为一个打开文件读写数据的操作,只不过这是一个特殊的操作罢了。接下来是一个关于socket通信的流程图:

python高级之网络编程

流程描述:

  1. 服务器根据地址类型(ipv4,ipv6)、socket类型、协议创建socket

  2. 服务器为socket绑定ip地址和端口号

  3. 服务器socket监听端口号请求,随时准备接收客户端发来的连接,这时候服务器的socket并没有被打开

  4. 客户端创建socket

  5. 客户端打开socket,根据服务器ip地址和端口号试图连接服务器socket

  6. 服务器socket接收到客户端socket请求,被动打开,开始接收客户端请求,直到客户端返回连接信息。这时候socket进入阻塞状态,所谓阻塞即accept()方法一直等到客户端返回连接信息后才返回,开始接收下一个客户端连接请求

  7. 客户端连接成功,向服务器发送连接状态信息

  8. 服务器accept方法返回,连接成功

  9. 客户端向socket写入信息(或服务端向socket写入信息)

  10. 服务器读取信息(客户端读取信息)

  11. 客户端关闭

  12. 服务器端关闭

3.socket模块一些方法

下面是socket模块里面提供的一些方法,让我们实现socke通信。

sk=socket.socket()

创建socket对象,这个时候可以指定两个参数,一个是family,另一个是type

family:AFINET(代表IPV4,默认参数),AFINET6(代表使用IPV6),AF_UNIX(UNIX文件系统通信)

type:SOCKSTREAM(TCP协议通信,默认参数),SOCKDGRAM(UDP协议通信) 默认不写的话,family=AFINET type=SOCKSTREAM

sk.bind(address)

sk.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。

sk.listen(backlog)

开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。 backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5 这个值不能无限大,因为要在内核中维护连接队列

sk.setblocking(bool)

是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。

sk.accept()

接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。

接收TCP 客户的连接(阻塞式)等待连接的到来

sk.connect(address)

连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。

sk.connect_ex(address)

同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061

sk.close()

关闭套接字

sk.recv(bufsize[,flag])

接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。

sk.recvfrom(bufsize[.flag])

与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。

sk.send(string[,flag])

将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。

sk.sendall(string[,flag])

将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。

内部通过递归调用send,将所有内容发送出去。

sk.sendto(string[,flag],address)

将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。

sk.settimeout(timeout)

设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )

sk.getpeername()

返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。

sk.getsockname()

返回套接字自己的地址。通常是一个元组(ipaddr,port)

sk.fileno()

套接字的文件描述符

4.聊天socket实现

好了,前戏做了那么多,到现在都还没写一行代码呢,接下来到了实战的步骤了。

 1 #server端实现:
 2 import socket  # 导入socket模块
 3 sk=socket.socket()  # 实例化socket对象
 4 address=("0.0.0.0",8000)  # 定义好监听的IP地址和端口,可以绑定网卡上的IP地址,但是生产环境中一般绑定0.0.0.0这样所有网卡上都能够接收并处理这个端口的数据了
 5 sk.bind(address)  # 绑定IP地址和端口
 6 sk.listen(5)  # 设定侦听开始并设定侦听队列里面等待的连接数最大为5
 7 
 8 while True:  # 循环,为了建立客户端连接
 9     conn,addr=sk.accept()  # conn拿到的是接入的客户端的对象,之后服务端和客户端通信都是基于这个conn对象进行通信,add获取的是连接的客户端的IP和端口
10     while True:  # 这个循环来实现相互之间聊天的逻辑
11         try:  # 为什么要使用try包裹这一块呢?因为在通信过程中客户端突然退出了的话,服务端阻塞在recv状态时将会抛出异常并终止程序,为了解决这个异常,需要我们自己捕获这个异常,这是在windows上,linux上不会抛出异常
12             data=conn.recv(1024)  # 定义接收的数据大小为1024个字节并接受客户端传递过来的数据,注意这里的数据在python3中是bytes类型的,在python3中网络通信发送和接收的数据必须是bytes类型的,否则会报错
13             if data:  # 假如客户端传递数据过来时
14                 print("-->",str(data,"utf-8"))  # 打印客户端传递过来的数据,需要从bytes类型数据解码成unicode类型的数据
15                 data=bytes(input(">>>"),"utf-8")  # 接收输入的数据并转换成bytes类型的数据
16                 conn.send(data)  # 将bytes类型的数据发送给客户端
17             else:  # 否则关闭这个客户端连接的对象,当客户端正常退出,执行了sk.close()时将不会发送数据到服务端,也就是说recv获取到的数据是空的
18                 conn.close()  # 这时关闭这个conn对象并退出当前循环等待下一个客户端对象来连接
19                 break
20         except ConnectionResetError as e:  # 捕获到异常之后,打印异常出来并退出循环等待下一个客户端连接
21             print(e)
22             break
23 
24 #client端实现
25 import socket  # 导入socket模块
26 sk=socket.socket()  # 实例化客户端对象
27 address=("127.0.0.1",8000)  # 设置客户端需要连接的服务端IP地址以及端口
28 sk.connect(address)  # 连接服务端的IP地址以及端口
29 while True:  # 循环实现对话
30     data=input(">>>").strip()  # 获取用户输入的数据
31     if data=="exit":  # 如果输入的是exit 关闭该对象并退出程序
32         sk.close()  # 关闭对象
33         break  # 退出循环
34     sk.send(bytes(data,"utf-8"))  # 发送刚输入的数据,要先转换成bytes类型的数据
35     data=str(sk.recv(1024),"utf-8")  # 接收服务端发送的数据,并将其转换成unicode数据类型
36     print("-->",data)  # 打印服务端传输过来的数据
显示代码
推荐阅读
  • python3+tkinter实践历程(四)——模仿CRT完成基于socket通信与tkinter的TCP串口客户端
    python3tkinter实践历程(四)——基于socket通信与tkinter的TCP串口客户端(仿CRT)文章目录系列文章目录分享背景制作背景最终功能工具截图展示代码详解系列 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 网络编程:其实就是在学socketsocket是什么?翻译过来称为套接字是对底层的TCPIPUDP等网络协议进行封装使得上层的应用程序开发者,不用直接接触这对复杂,丑陋的协议在程序 ... [详细]
  • 今天搭建了redis环境,使用自带的benchmark进行了性能测试选择测试键的范围大小默认情况下面,基准测试使用单一的key。在一个基于内存的数据库里,单一key测试和真实情况下 ... [详细]
  • python图书管理系统类_Python标准库socketserver使用线程混入实现异步TCP服务器
    推荐图书:《Python程序设计开发宝典》,ISBN:978-7-302-47210-0,董付国,清华大学出版 ... [详细]
  • Docker 快速入门指引
    本文最早发表于本人博客:Docker快速入门指引Docker是什么?Docker是Docker.Inc公司开源的一个基于LXC技术之上构建的Container容器引擎,基于Go语言 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
author-avatar
-qone0_784
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有