Python 网络编程

  • 网络基础
    • 为什么要使用通信协议
    • TCP/IP 简介
      • IP 协议
      • TCP 协议
    • UDP 简介
    • TCP 协议和 UDP 协议的区别
    • Socket 简介
  • TCP 编程
    • 创建 TCP 服务器
    • 创建 TCP 客户端
    • 执行 TCP 服务器和客户端
  • UDP 编程
    • 创建 UDP 服务器
    • 创建 UDP 客户端
    • 执行 UDP 服务器和客户端

计算机网络就是把各个计算机连接到一起,让网络中的计算机可以互相通信。网络编程就是如何在程序中实现两台计算机的通信。

网络基础

为什么要使用通信协议

计算机为了联网,就必须规定通信协议,早起的计算机网络,由各厂商自己规定一套协议,IBM、Apple 和 Microsoft 都有各自的网络协议,互不兼容。
为了实现全世界所有不同类型的计算机连接起来,必须规定一套全球通用的协议,因此,互联网协议簇(Internet Protocol Suite)即通用协议标准出现了。Internet 是由 inter 和 net 两个单词组合起来的,原意就是连接“网络”的网络,有了 Internet,任何私有网络,只要支持这个协议,就可以接入互联网。

TCP/IP 简介

因为互联网协议包含了上百种协议标准,但是最重要的两个协议是 TCP 和 IP 协议,所以,大家把互联网的协议简称 TCP/IP 协议。

IP 协议

在通信时,通信双方必须知道对方的标识,好比发送快递必须知道对方的地址。互联网上每个计算机的唯一表示就是 IP 地址。IP 地址实际上是一个32位整数(简称 IPv4),它是以字符串表示的 IP 地址,如 172.16.254.1,实际上是把32位整数按8位分组后的数字表示

172 ——> 10101100
16 ——> 00010000
254 ——> 111111110
1 ——> 00000001

IP 协议负责把数据从一台计算机通过网络发送到另一台计算机。数据被分割成一小块一小块,类似于一个大包裹拆分成几个小包裹,然后通过 IP 包发送出去。由于互联网链路复杂,两台计算机之间经常有多条线路,因此,路由器就负责决定如何把一个 IP 包转发出去。IP 包的特点是按块发送,途径多个路由,但不保证都能到达,也不能保证顺利到达。

TCP 协议

TCP协议则是建立在 IP 协议之上的。TCP 协议负责在两台计算机之间建立可靠连接,保证数据包按顺序到达。TCP 协议会通过3次握手建立可靠连接。
然后需要对每个 IP 包进行编号,确保对方按顺序收到,如果包丢了,就自动重发。

许多常用的更高级的协议都是建立在 TCP 协议基础上的,比如用于浏览器的
HTTP 协议、发送邮件的 SMTP 协议等。一个 TCP 报文除了包含要传输的数据外,还包含源 IP 地址和 目标 IP 地址、源端口和目标端口。

端口有什么作用?在两台计算机通信时,只发送 IP 地址是不够的,因为同一台计算机上运行着多个网络程序。一个 TCP 报文来了之后,到底是交给浏览器还是 QQ,就需要端口号来区分。每个网络程序都向操作系统申请唯一的端口号,这样,两个进程在两台计算机之间建立网络连接就需要各自的 IP 地址和各自的端口号。

一个进程也可能同时与多个计算机建立链接,因此它会申请很多端口。端口号不是随意使用的,而是按照一定的规定进行分配。例如,80 端口分配给 HTTP服务,21 端口分配给 FTP 服务。

UDP 简介

相对 TCP 协议,UDP 协议则是面向无连接的协议。使用 UDP 协议时,不需要建立链接,只需要知道对方的 IP 地址和端口号,就可以直接发数据包。 但是,数据无法保证一定到达。虽然用 UDP 传输数据不可靠,但它的优点是比 TCP 协议的速度快。对于不要求可靠到达的数据而言,就可以使用 UDP 协议。

TCP 协议和 UDP 协议的区别

⊙TCP(Transmission Control Protocol),又叫传输控制协议;TCP 是面向连接的,并且是一种可靠的协议,在基于 TCP 进行通信时,通信双方需要先建立一个 TCP 连接,建立连接需要经过三次握手,握手成功才可以进行通信,而断开连接要进行4次

⊙UDP(User Datagram Protocol),又叫用户数据报协议;UDP 是一种面向无连接,且不可靠的协议,在通信过程中,它并不像 TCP 那样需要先建立一个连接,只要(目的地址,端口号,源地址,端口号)确定了,就可以直接发送信息报文,并且不需要确保服务端一定能收到或收到完整的数据。它仅仅提供了校验和机制来保障一个报文是否完整,若校验失败,则直接丢弃报文,不做任何处理。

TCP与UDP的区别:

基于连接与无连接:TCP基于面向连接,UDP基于面向无连接;

系统资源的要求:TCP占用的系统资源较多,UDP较少;

程序结构较简单:TCP程序结构复杂,UDP程序结构简单;

流模式与数据报模式:TCP是流模式,UDP是数据报模式;

可靠性:TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。

TCP 与 UDP 的应用场景

从特点上我们已经知道,TCP 是可靠的但传输速度慢 ,UDP 是不可靠的但传输速度快。因此在选用具体协议通信时,应该根据通信数据的要求而决定。

若通信数据完整性需让位与通信实时性,则应该选用 TCP 协议(如文件传输、重要状态的更新等);反之,则使用 UDP 协议(如视频传输、实时通信等)。

Socket 简介

为了让两个程序通过网络进行通信,二者均必须使用 Socket 套接字。Socket 的英文原义是 “孔” 或 “插座”,通常也称作 “套接字”,用于描述 IP 地址和端口,它是一个通信连的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。

在 Internet 上的主机一般运行了多个服务软件,同时提供几种服务。每种服务器都打开一个 Socket,并绑定到一个端口上,不同的端口对应于不同的服务。

123.123.123.123
客户端 <—— 端口2324 —— Socket <—— 端口2324 —— 服务器
客户端 —–— 端口23 —–—> Socket ——> 端口23 ——> 服务器 10.1.1.1

Socket 正如其英文原意那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供 220 V 交流电,有的提供 110V 交流电,有的则提供有线电视节目。客户软件将插头插到不同编号的插座,就可以得到不同服务。

在 Python 中使用 socket 模块的 socket() 函数就可以完成,语法格式如下:

s = socket.socket(AddressFamily, Type)

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

例如,为了创建 TCP/IP 套接字,可以用下面的方式调用 socket.socket():

tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

同样,为了创建 UDP/IP 套接字,需要执行以下语句:

udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

创建完成后,生成一个 socket 对象,socket 对象的主要方法如下:

函数 描述
s.bind() 绑定地址(host,port)到套接字,在AF_INET 下,以元组(host,port)的形式表示地址
s.listen() 开始 TCP 监听。backlog 指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为 5 就可以了。
s.accept() 被动接受 TCP 客户端连接(阻塞式),等待连接的到来
s.connect() 主动初始化 TCP 服务器连接,一般 address 的格式为元组(hostname,port),如果连接出错,返回 socket.error 错误
s.recv() 接收 TCP 数据,数据以字符串形式返回,bufsize 指定要接收的最大数据量。flag 提供有关消息的其他信息,通常可以忽略。
s.send() 发送 TCP 数据,将 string 中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于 string 的字节大小
s.sendall() 完整发送 TCP 数据。将 string 中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回 None,失败则抛出异常。
s.recvfrom() 接收 UDP 数据,与 recv() 类似,但返回值是(data,address)。其中 data 是包含接收数据的字符串,address 是发送数据的套接字地址。
s.sendto() 发送 UDP 数据,将数据发送到套接字,address 是形式为(ipaddr,port) 的元组,指定远程地址。返回值是发送的字节数。
sc.close() 关闭套接字

TCP 编程

由于 TCP 连接具有安全可靠的特性,所以 TCP 应用更为广泛。创建 TCP 连接时,主动发起连接的叫客户端被动响应连接的叫服务器

例如,当我们在浏览器中访问一个网站时,我们自己的计算机就是客户端,浏览器会主动向网站的服务器发起连接。如果一切顺利,服务器接收了我们的连接,一个 TCP 连接就建立起来了,后面的通信就是发送网页内容了。

创建 TCP 服务器

创建 TCP 服务器的过程,类似于生活中接听电话的过程。如果要接听别人的来电,首先需要购买一部手机,然后安装手机卡。接下来,设置手机为接听状态,最后等待对方来电。

如同上面接听电话的过程一样,在程序中,如果想要完成一个 TCP 服务器的功能,需要的流程如下:
⊙ 使用 socket() 创建一个套接字
⊙ 使用 bind() 绑定 IP 和 port
⊙ 使用 listen() 使套接字变为可被动连接
⊙ 使用 accpet() 等待客户端的连接
⊙ 使用 recv/send() 接收发送数据
例如,使用 socket 模块,通过客户端浏览器向本地服务器(IP 地址为 127.0.0.1) 发起请求,服务器接到请求,向浏览器发送 “Hello World”。具体代码如下:

# server.py
import socket
host = '127.0.0.1'          # 主机IP
port = 8080                 # 端口号
web = socket.socket()       # 创建 socket 对象
web.bind((host, port))      # 绑定端口
web.listen(5)               # 设置最多连接数
print('服务器等待客户端连接...')
# 开启死循环
while True:conn,addr = web.accept() # 建立客户端连接data = conn.recv(1024)   # 获取客户端请求数据print(data)conn.sendall(b'HTTP/1.1 200 OK\r\n\r\nHello World') # 向客户端发送数据conn.close()             # 关闭连接

运行结果:

然后打开谷歌浏览器,输入网址:127.0.0.1:8080(服务器 IP 地址是 127.0.0.1,端口号是 8080),成功连接服务器以后,浏览器会显示“Hello World”。运行结果如图:

创建 TCP 客户端

TCP 的客户端要比服务器简单很多,如果说服务器是需要自己买手机、插手机卡、设置铃声、等待别人打电话流程的话,那么客户端就只需要找一个电话亭,拿起电话拨打即可,流程要少很多。

上面,我们利用浏览器作为客户端接收数据,下面,创建一个 TCP 客户端,通过该客户端向服务器发送和接收消息。具体代码如下:

# client.py
import socket
s = socket.socket()                     # 创建 TCP/IP 套接字
host = '127.0.0.1'                      # 获取主机地址
port = 8080                             # 设置端口号
s.connect((host, port))                   # 主动初始化 TCP 服务器连接
send_data = input("请输入要发送的数据:")  # 提示用户输入数据
s.send(send_data.encode())              # 发送 TCP 数据
# 接收对方发送过来的数据,最大接收 1024 个字节
recvData = s.recv(1024).decode()
print("接收到的数据为:", recvData)
s.close()   # 关闭套接字

打开两个 cmd 命令行窗口,先运行 server.py 文件,再运行 client.py 文件。接着,在 client.py 窗口输入“hi”,此时 server.py 窗口会接收到消息,并且发送“Hello World”。运行结果如下:实现了客户端和服务器通信效果

执行 TCP 服务器和客户端

在上面的例子中,我们设置了一个服务器和一个客户端,并且实现了客户端和服务器之间的通信。根据服务器和客户端的执行流程,可以总结出 TCP 客户端 和服务器的通信模型,如下图:

既然客户端和服务器可以使用 Socket 进行通信,那么客户端就可以向服务器发送文字,服务器接收到消息后,显示消息内容并且输入文字返回给客户端。客户端接收到响应,显示该文字,然后继续向服务器发送消息。这样,就可以实现一个简易的聊天窗口。当由乙方输入 “byebye” 时,则退出系统,中断聊天。可以根据以下步骤实现该功能。

(1) 创建 server.py 文件,作为服务器程序,代码如下:

# server.py
import socket
host = socket.gethostname()     # 获取主机地址
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建 TCP/IP 套接字
s.bind((host, port))            # 绑定地址(host,port)到套接字
s.listen(1)                     # 设置最多连接数量
sock, addr = s.accept()         # 被动接收 TCP 客户端连接
print("连接已经建立")
info = sock.recv(1024).decode() # 接收客户端数据
while info != 'byebye':         # 判断是否退出if info:print("接收到的内容:" + info)send_data = input("输入发送内容:")       # 发送消息sock.send(send_data.encode())           # 发送 TCP 数据if send_data == 'byebye':               # 如果发送 byebye,则退出break       info = sock.recv(1024).decode()         # 接收客户端数据
sock.close()        # 关闭客户端套接字
s.close()           # 关闭服务器套接字

(2) 创建 client.py 文件,作为客户端程序,具体代码如下:

# client.py
import socket
s =  socket.socket()        # 创建 TCP/IP 套接字
host = socket.gethostname() # 获取主机地址
port = 12345                # 设置端口号
s.connect((host, port))     # 主动初始化 TCP 服务器连接
print("已连接")
info = ''
while info != 'byebye':                 # 判断是否退出send_data = input("输入发送内容:")   # 输入内容s.send(send_data.encode())          # 发送 TCP 数据if send_data == 'byebye':           # 判断是否退出breakinfo = s.recv(1024).decode()        # 接收服务器数据print("接收到的内容:" + info)
s.close()       # 关闭套接字

打开 2 个 cmd 命令行,分别运行 server.py 和 client.py 文件,如图:

接下来,在 client.py 窗口中,输入 “土豆土豆,我是地瓜”,然后按下。此时,在 server.py 窗口中将显示 client.py 窗口发送的消息,并提示 server.py 窗口输入发送内容,如图:

当输入 “byebye” 时,结束对话,如图:

UDP 编程

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

  • 语音广播
  • 视频
  • 聊天软件
  • TFTP(简单文件传送)
  • SNMP(简单网络管理协议)
  • RIP(路由信息协议,如报告股票市场、航空信息)
  • DNS(域名解释)

和 TCP 类似,利用 UDP 的通信双方也分为客户端和服务器。

创建 UDP 服务器

UDP 服务器不需要 TCP 服务器那么多的配置,因为它们不是面向连接的。除了等待传入的连接之外,几乎不需要做其他工作。下面实现了一个将摄氏温度转化为华氏温度的功能。

# udp_server.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 创建 UDP 套接字
s.bind(('127.0.0.1', 8888)) # 绑定地址(host, port)到套接字
print('绑定UDP到8888端口')
data, addr = s.recvfrom(1024)   # 接收数据
data = float(data)*1.8 + 32     # 转化公式
send_data = '转换后的温度(单位:华氏温度):' + str(data)
print('Received from %s %s.' % addr)
s.sendto(send_data.encode(), addr) # 发送给客户端
s.close()       # 关闭服务器套接字

上述代码中,使用 socket.socket() 函数创建套接字,参数设为 socket.SOCK_DGRAM ,表明创建的是 UDP 套接字。此外需要注意, s.recvfrom() 函数生成的 data 数据类型是 byte,不能进行四则运算,需要将其转化为 float 浮点型数据。最后在使用 sendto() 函数发送数据时,发送的数据必须是 byte 类型,所以需要使用 encode() 函数将字符串转为 byte 类型

运行结果:

创建 UDP 客户端

创建一个 UDP 客户端程序的流程很简单,具体步骤如下:

  • 创建客户端套接字
  • 发送/接收数据
  • 关闭套接字

具体代码如下:

# udp_client.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    # 创建 UDP 套接字
data = input("请输入要转换的问题(单位:摄氏度):")        # 输入要转换的温度
s.sendto(data.encode(), ('127.0.0.1', 8888))            # 发送数据
print(s.recv(1024).decode())                            # 打印接收数据
s.close()                                               # 关闭套接字

上述代码中,主要就是接收的数据和发送的数据类型都是 byte。所以发送时,使用 encode() 函数将字符串转化为 byte。而在输出时,使用 decode() 将 byte 类型数据转换为字符串,方便用户阅读。

在两个 cmd 窗口中分别运行 udp_server.py 和 udp_client.py,然后在 udp_client.py 窗口中输入要转换的摄氏度,udp_client.py 窗口会立即显示转换后的华氏度。
运行结果如图:

执行 UDP 服务器和客户端

在 UDP 通信模型中,在通信开始之前,不需要建立相关的连接,只需要发送数据即可,类似于生活中的“写信”。 UDP 通信模型如图:

【Python笔记】网络编程相关推荐

  1. Python学习笔记:网络编程

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  2. Python Socket网络编程(二)局域网内和局域网与广域网的持续通信

    目录 前言 IP地址 简介 公有IP 私有IP 局域网之间网络通信 前提 功能描述 源码 运行结果 局域网与广域网网络通信 前提 源码 结语 前言 本系列博客是笔者学习Python Socket的过程 ...

  3. Python Socket网络编程(一)初识Socket和Socket初步使用

    目录 前言 网络编程 实质 IP地址和端口 数据传输协议 协议 Socket 概念 套接字 socket对象方法 初步使用 功能 源码 运行结果 结语 前言 本系列博客是笔者学习Python Sock ...

  4. Python高级网络编程系列之第一篇

    在上一篇中我们简单的说了一下Python中网络编程的基础知识(相关API就不解释了),其中还有什么细节的知识点没有进行说明,如什么是TCP/IP协议有几种状态,什么是TCP三次握手,什么是TCP四次握 ...

  5. Python之网络编程(TCP套接字与UDP套接字)

    文章目录 基于tcp的套接字 实现目标 tcp服务端源码 tcp客户端源码 tcp效果实现 基于udp的套接字 udp作用介绍 udp服务端源码 udp客户端源码 udp效果实现 用udp实现一个时间 ...

  6. python recv_python网络编程调用recv函数完整接收数据的三种方法

    最近在使用python进行网络编程开发一个通用的tcpclient测试小工具.在使用socket进行网络编程中,如何判定对端发送一条报文是否接收完成,是进行socket网络开发必须要考虑的一个问题.这 ...

  7. 0x011.Python学习-网络编程、PortScan

    Python3 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口 ...

  8. 用 Python 写网络编程(四)

    本文首发于TesterHome社区,作者是资深游戏测试开发工程师陈子昂.用 Python 写网络编程共四篇,今天分享的是第四篇.原文链接:https://testerhome.com/topics/2 ...

  9. Python 异步网络编程实战

    Python 异步网络编程实战 - songcser - 掘金小册 小册介绍 第一部分是对 Python 协程的讲解,从字节码开始简单讲解了 Python 虚拟机的执行过程,可以大体了解到 Pytho ...

  10. python笔记之编程风格大比拼

    python笔记之编程风格大比拼 虽然我的python age并不高,但我仍然愿意将我遇到的或者我写的有趣的python程序和大家一块分享,下面是我找到的一篇关于各类python程序员的编程风格的比较 ...

最新文章

  1. linux pipe函数 重定向,I/O重定向和管道——《Unix/Linux编程实践教程》读书笔记(第10章)...
  2. LeetCode 207. Course Schedule--有向图找环--面试算法题--DFS递归,拓扑排序迭代--Python
  3. 获取mysql可行方法_Mysql学习Java实现获得MySQL数据库中所有表的记录总数可行方法...
  4. shell编程--流程控制for,do-while,if-then,break,continue,case等
  5. 网站的服务器区域可以造假吗,如何伪造DNS服务器?
  6. webcomponents安装了没有用_Web Components 入门实例教程
  7. html页面foot,HTML tfoot用法及代码示例
  8. C# Struct的内存布局
  9. .NET下一种简单的调试诊断方法
  10. Java中String.format()的简单用法介绍
  11. php里= 啥意思,PHP natcasesort() 函数 | 菜鸟教程
  12. 【报告分享】 百度2021国潮骄傲搜索大数据报告-百度x人民网(附下载)
  13. 【工具篇】使用OpenCV播放视频并截取图片
  14. 计算机四级题库百度云资源,计算机四级题库
  15. 阿里玄难:面向不确定性的软件设计几点思考
  16. dataframe横向和纵向拼接
  17. android拍照保存照片方向,android 拍照的照片方向问题,读取图片EXIF信息
  18. 安卓手机更新过程手机乱码_王者荣耀安卓更新更新时出现乱码解决办法
  19. Request和Response的概述及其方法
  20. 四种常见的 POST 提交数据方式 专题

热门文章

  1. 满足ThreadLocal目的
  2. timerfd_create Function not implemented问题
  3. source insight 4 破解
  4. linux box 信息发布,使用Instantbox快速搭建一个开箱即用的Web端临时Linux系统
  5. SQL Server便利名称
  6. sql server 关联_SQL Server中的关联规则挖掘
  7. 使用DBATools编写SQL Server对象脚本
  8. ssis for循环容器_使用SSIS ForEach Loop容器以日期顺序处理文件
  9. Centos 7 安装shellcheck
  10. mongodb count 导致不正确的数量(mongodb count 一个坑)