网络编程(python)

1.1网络基础

当今的时代是一个网络的时代,网络无处不在。而我们前面学习编写的程序都是单机的,即不能和其他计算机上的程序进行通信。为了实现不同计算机之间的通信,就需要使用网络编程。下面我们来了解一下网络相关的基础知识。

1.1.1 为什么要使用通信协议

计算机为了联网,就必须规定通信协议。早期的计算机网络都是由各厂商自己规定一套协议,IBM、Apple和Microsoft都有各自的网络协议,互不兼容;这就好比一群人有的说英语,有的说中文,有的说德语,说同一一种语言的人可以交流,不同的语言之间就无法交流了。
为了把全世界的所有不同类型的计算机都连接起来,就必须规定一套 全球通用的协议,为了实现下联网这个目标,互联网协议簇(Internet Protocol Suite)就是通用协议标准出现了。Internet 是由inter和net两个单词组合起来的,原意就是连接“网络”的网络,有了lnternet,任何私有网络,只要支持这个协议,就可以联入互联网。

1.1.2 TCP/IP简介

因为互联网协议包含了上百种协议标准,但是最重要的两个协议是TCP和IP协议,所以,大家把互联网的协议简称TCP/IP协议。
1.IP协议
在通信时,通信双方必须知道对方的标识。好比发送快递必须知道对方的地址。互联网上每个计机的唯一标识就是IP地址。IP地址实际上是一个32位整数(称为IPv4),以字符串表示的IP地址如172.16.254.1 实际上是把32位整数按8位分组后的数字表示,目的是便于阅读。
IP协议负责把数据从一台计算机通过网络发送到另一台计算机。数据被分割成一小块一小块, 类似于将一一个大包裹拆分成几个小包裹,然后通过IP包发送出去。由于互联网链路复杂,两台计算机之间经常有多条线路,因此,路由器就负责决定如何把一个 IP包转发出去。IP包的特点是按块发送,途经多个路由,但不保证都能到达,也不保证顺序到达。

2. TCP协议
TCP协议是建立在IP协议之上的。TCP协议负责在两台计算机之间建立可靠连接,保证数据包按顺序到达。TCP协议通过3次握手建立可靠连接。
然后,对每个IP包编号,确保对方按顺序收到,如果包丢掉了,就自动重发,常用的更高级的协议都是建立在TCP协议基础上的。比如用于浏览器的HTTP协议、发送邮件的SMTP协议等。一个 TCP报文除了包含要传输的数据外,还包含源地址和目标IP地址,源端口和目标端口。
端口有什么作用呢?在两台计算机通信时,只发IP地址是不够的,因为同一台计算机上运行着多个网络程序。一个 TCP报文来了之后,到底是交给浏览器还是QQ,就需要端口号来区分。每个网络程序都向操作系统申请唯一的端口号, 这样,两个进程在两台计算机之间建立网络连接就需要各自的IP地址和各自的端口号。
一个进程也可能同时与多个计算机建立连接,因此它会申请很多端口。端口号不是随意使用的,而是按照一定的规定进行分配。例如,80 端口分配给HTTP服务,21 端口分配给FTP服务。

1.1.3 UDP 简介

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

1.1.4 Socket简介

为了让两个程序通过网络进行通信,二者均必须使用Socket套接字。Soket的英文原义是“孔”或“插座”,通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Intemet上的主机上一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。

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

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

s= socket.socket(AddressFamily.Typype)

函数socket.socket创建一个socket, 返回该soket 的描述符,该函数带有两个参数:

  • :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)

Scoket对象的主要方法:

函数描述
s.bind()绑定地址(host,port)到套接字,在AF_INET下以元组(host,port)的形式表示地址
s.listen()开始TCP监听backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了
s.accept()被动接收TCP客户端连接,并且以阻塞方式等待连接的到来
s.connect()主动初始化TCP服务器连接,一般addres的格式为元组(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) 的元组,指定远程地址。返回值是发送的字节数
s.close()关闭套接字

1.2TCP编程

1.2.1创建TCP服务器

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

  • 使用 soeke创建一个套接字。
  • 使用bind 绑定和port。
  • 使用listen 使套接字变为可以被动连接。
  • 使用accept等待客户端的连接。
  • 使用recv/send 接收发送数据。

使用Socket模块,通过客户端浏览器向本地服务器(IP 地址为127.0.0.1)发起请求,服务器接到请求,向浏览器发送"Hello World”。具体代码如下:
server.py

# encoding=utf-8
import socket
host='127.0.0.1'
port=8080
web=socket.socket()       #创建socket对象
web.bind((host,port))     #绑定ip地址 端口
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 word')   #向客户端发送数据
    conn.close()      #关闭链接

输出内容

服务器等待端链接
#第一次请求
b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\r\nAccept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie:csrftoken=dnUhDDSo8t545Irx5nQe5xNcpoiFHKeD1Eyftihuu3FLLgDQ5XkK8IGG95AFvseR\r\n\r\n'

#第二次请求
b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\r\nAccept:image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:8080/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie:csrftoken=dnUhDDSo8t545Irx5nQe5xNcpoiFHKeD1Eyftihuu3FLLgDQ5XkK8IGG95AFvseR\r\n\r\n'
1.2.2 创建TCP客户端

TCP的客户端要比服务器简单很多,如果说服务器是需要自己买手机、插手机卡、设置铃声、生待别人打电话流程的话,那么客户端就只需要找一个电话亭, 拿起电话拨打即可,流程要少很多。
我们使用浏览器作为客户端接收数据。下面创建一个TCP客户端,通过该客户端向服务器发送和接收消息。创建一个 client.py 文件,具体代码如下:
client.py脚本如下:

# encoding=utf-8
import socket
host='127.0.0.1'
port=8080
web=socket.socket()       #创建socket对象
web.connect((host,port))     #绑定ip地址 端口
send_data=input("请输入要发送到的数据:")   # 提示用户输入数据
web.send(send_data.encode())   #发送TCP数据
recvData=web.recv(1024).decode()
print("接收到的数据为:",recvData)
web.close()

运行结果:

client端如下
请输入要发送到的数据:hi
接收到的数据为: HTTP/1.1 200 ok
Hello word

server端如下:
服务器等待端链接
b’hi’

1.2.3 执行TCP服务器和客户端

在这里插入图片描述

我们设置了一个服务器和一个客户端,并且实现了客户端和服务器之间的通信。根据服务器和客户端执行流程,可以总结出TCP客户端和服务器通信模型,如图19.10所示。
server端

# encoding=utf-8
import socket
#Server代码
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()       #关闭服务器套接字

client端

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

在这里插入图片描述

1.3 UDP 编程

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

  • 语音广播。
  • 视频。
  • 聊天软件。
  • TFTP(简单文件传送)。
  • SNMP(简单网络管理协议)
  • RIP(路由信息协议, 如报告股聚市场。航空信息)。
  • DNS(域名解释)。
    和TCP类似,使用UDP的通信双方也分为客户端和服务器。
1.3.1 创建UDP服务器

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

实例:将摄氏温度转换为华氏温度。
在客户端输入要转换的摄氏温度,然后发送给服务器,服务器根据转化公式,将摄氏温度转换为华氏温度,发送给客户端显示。具体代码如下:

UDP Server端

# encoding=utf-8
import socket
#Server端
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()   #关闭服务端套接字

UDP Client端

# encoding=utf-8
import socket
#Client端
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()

在这里插入图片描述

1.3.3 执行UDP服务器和客户端

UDP通信模型中,在通信开始之前, 不需要建立相关的链接,只需要发送数据即可,类似于生活中的“写信”。UDP通信模型如图
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值