[Python基础17]网络编程&TCP编程&UDP编程

  • 网络基础知识
    什么是网络
    什么是网络编程
    IP地址是什么鬼
    端口号又是什么鬼
    据说还有个网络传输协议
  • TCP编程
  • UDP编程

1. 网络传输协议

1.1. 什么是网络

网络是将我们运行的多台个人PC,通过有线网或者无线网连接起来,方便多台电脑之间的数据传输而出现的,如我们个人PC如果单独使用的时候,只能当成单台电脑运行单机软件,写写文档、看看下载好的电影、玩玩单机游戏等等,如果此时想和其他使用电脑的人说句话~你只能通过张嘴喊话的方式了;如果电脑联网的话,就可以通过飞秋、QQ等各种手段实现,常见的网络都有哪些呢

网络根据使用的范围和区域的不同,划分了不同的几个档次
单机:单机其实也是一个网络环境,只能访问当前PC的数据,单机的网络IP地址:127.0.0.1
局域网:两台或者两台以上的电脑,通过交换机或者路由器进行互相连接,在一定的范围内局域网的PC可以实现互相通信的目的;一般情况局域网的PC数量在2台到几千台PC之间
城域网:是一种大型的局域网,可以访问的数据信息更多,通常情况下,城域网这个术语是从城市网络抽象出来的,也就是将一个城市中的PC进行网络连接实现数据共享的手段
广域网:通常是指代的跨地域的网络通信,一般情况下以国家或者地域为单位,让数据通信更加的广阔

网络:其实就是通过运营商提供的一种数据通信手段,将不同的PC进行连接,实现不同的PC之间数据通信为目的的一种手段,根据网络操作的范围划分单机、局域网、城域网、广域网等不同的网络访问层次结构。

1.2. 什么是网络编程

如果有了网络之后,网络中的所有数据都直接可以让别人访问的话,就会出现非常严重的数据安全问题;次数就需要一种手段,将数据通过网络进行共享的同时增加限制访问权限;

网络编程就是通过编程的手段,让不同的PC之间可以使用恰当的方式进行数据的共享,同时添加各种限制权限让网络数据更加安全的一种技术操作。

在网络编程中,会出现一些专业的术语名词,需要简单了解一下
服务器:专门用于数据共享的PC,将数据共享给所属网络中其他的PC,其他的PC可以通过网络和服务器提供的访问手段来访问服务器上的数据,如:淘宝就有自己的服务器,我们可以通过浏览器访问http://www.taobao.com来访问淘宝服务器上的数据
客户端:在网络中获取数据的PC,当我们访问淘宝服务器的时候,我们自己的PC就是客户端

1.3. 网络数据传输:ip地址

如果一旦多个PC组成一个网络,就会出现这样一个问题,通过什么样的方式来确定某一个PC就是它自己呢,就如同让你怎么证明你就是你自己一样,生活中,我们会通过身份证号码来证明自己就是唯一的自己;网络中一般通过IP地址来确定网络中的某一个PC

网络中通过IP地址来确定某个唯一的电脑

IP地址也是一种网络协议,英文名称是Internet Protobcal Address,它提供了一种统一的地址格式,为网络中的PC分配一个唯一的整数序列,通常IP地址时一个二进制的数字序列,为了方便我们理解,转换为10进制整数,如:01100100.00000100.00000101.00000110就是一个IP地址,转换成十进制之后就是:100.4.5.6;如果大家了解过二进制的表示方式的话,就能看出来IP地址中的每一组数据的范围都是0~255之间

IP地址的编码方案:为了区分不同的机构使用的PC,约定俗称的将IP地址划分成了不同的类型,一般有A/B/C/D/E五类

IP地址分类

我们已经看出来了,IP地址可以表示的PC时期是非常有限的,总共能表示的电脑个数大概43亿个左右,如果一旦PC数量超出这个范围就表示不了了;所以在近些年,将原来的这样的IP地址表示方式,定义为IPv4版本;并且推出了IPv6的表示方式,IPv6可以标识更加多的PC;对于这部分的了解,大家有时间的时候可以自己拓展一下。

1.4. 网络数据传输:端口号

当我们的电脑已经处于网络中时,就可以进行数据通信了,但是此时又遇到这样一个问题;我们在自己的PC上可能同时打开了多个程序:QQ,微信、淘宝,如果我们向淘宝服务器发起了数据请求,淘宝服务器返回了我们需要的数据,那这些数据根据IP地址找到了我们的个人PC,但是数据应该交个那个应用程序呢?

数据请求过程

此时,就如同我们从淘宝上买了一件商品,商品通过快递(网络)寄送到我们的地址了,但是怎么样找到对应的人呢?答案很简单:通过我们收货人姓名来确定收快递的是谁。在网络中我们访问的数据,怎么区分是哪个程序呢,通过端口(Port)来进行确定,每一个端口都会对应唯一的一个应用程序,如浏览器访问的数据,是通过80端口进行数据传输的,FTP服务器是通过21端口进行数据传输的等等

常见的端口:

端口号描述
21FTP服务器文件传输接口
22SSH连接端口
23Telnet连接端口
25SMTP邮件服务端口
80浏览器访问网页的端口
109pop3邮件服务端口
443浏览器安全访问网页端口
1521oracle数据库使用端口
3306mysql数据库使用端口
1.5. 网络数据传输:网络传输协议

我们有了网络,有了IP地址,有了端口号Port,已经可以实现网络中不同的PC上的程序进行数据通信了,但是数据通信没有问题的前提下又出现了新的问题:不同的PC上的数据可能互相不认识!

如果现实生活中,每个人都是一个单独的PC,我们有了手机就算是有了网络,端口号就像每个人的手机号码一样都是唯一的,此时可以实现不同的人之间通过PC来进行通话了,也就是进行数据通信了;
如果你拨出一个号码对方接起了你的电话,你俩开始通信,你说的是本地方言,对方说的是阿拉伯语,你们说的话也就是数据,对方肯定是接收到了,但是~你翻译不了阿拉伯语,对方也翻译不了普通话,此时的数据通信尽管有了,但是数据由于解析不了,就相当于无效的通信!
Bingo!如果我们互相约定了,双方都使用我们大中华的标准普通话进行交流,你说的对方听懂了,对方说的你也听懂了,这样才是有效的通信——这里双方约定使用普通话交流,就是约定了一个通话协议

如果我们在网络中,约定了传输数据使用什么样的方式组织数据,就是网络协议

网络协议,就是网络数据传输协议,简称为传输协议,是为网络中不同PC和程序之间的有效数据通信而制定的一种数据组织和传输方式

常见的网络传输协议要归结到国际标准化组织(ISO)制定的开发系统互联模型(OSI)

OSI模型

名称层次功能
物理层1实现计算机系统与网络间的物理连接
数据链路层2进行数据打包与解包,形成信息帧
网络层3提供数据通过的路由
传输层4提供传输顺序信息与响应
会话层5建立和中止连接
表示层6数据转换、确认数据格式
应用层7提供用户程序接口

常见协议

网络传输常见协议

我们可以看到,前面了解的IP协议是底层的一种传输协议;基于IP协议在主机层次有TCP点对点的传输协议和UDP的广播协议等等,再向上应用层有FTP文件传输服务HTTP超文本数据传输协议等等。关于OSI模型和对应的数据传输协议,大家可以自行了解扩展一下。


什么是TCP协议

  • TCP网络编程——服务端程序开发
  • TCP网络编程——客户端程序开发

1. 关于TCP协议那点事儿

TCP协议是一种面向连接、保证数据传输的高可靠性的,一对一的传输层协议

TCP协议保证连接的可靠性是通过它的通信特征来确定的:首先保证正确建立可靠的连接,主要通过三次通信握手来确定;其次保证数据包的数量和顺序不会丢失和错乱,如果发现数据包发送失败会重新发送;第三当连接终止时,连接双方都需要独立关闭自己的连接,通过四次挥手确定连接断开。

建立可靠连接的三次握手
断开连接的四次挥手操作
从上面的操作过程我们可以发现一个规律,服务器端总是处于等待状态,客户端会主动发起和服务器的连接,通过三次握手建立可靠的连接并进行数据的传输。一直到最后客户端发起关闭连接请求,经过四次挥手操作断开和服务器之间的连接

所以正常情况下, TCP网络编程一般是首先开发服务端程序,然后开发客户端程序。

2. TCP服务端编程

python中的网络编程,就类似生活中将两台PC用网线连接起来一样,网线表示网络,需要水晶头将网线连接到电脑上才能正常的操作;python提供了这样的水晶头:套接字(socket)

TCP网络编程就是这么回事

2.1 API解析
  • socket模块:TCP网络编程,需要引入这个模块

  • socket():socket模块中的socket()对象,可以用于创建套接字:socket(family, type)
    参数family:连接的IP地址类型,socket.AF_INET表示的是IPv4的地址,socket.AF_INET6表示的是IPv6的地址
    参数type:连接数据传输类型,使用socket.SOCK_STREAM表示使用流协议(TCP)
    返回值:一旦创建成功,返回一个套接字对象,姑且命名为sc

  • bind():用于将套接字和主机IP以及端口号Port进行绑定,就是上面例图中将网线插到电脑上
    bind()是socket对象的方法,可以直接通过socket对象调用
    bind()方法只接受一个元组类型的参数,将ip地址和端口填写进去即可
    sc.bind((“192.168.1.1”, 8080))

  • listener(count):监听连接的方法,一般在服务端编程中使用,调用socket对象的listener()方法,就会让服务器程序处于等待客户端连接
    参数count:一个整数数据,表示允许最大的连接数量

  • accept():接收客户端的连接,这是一个阻塞方法,一旦程序执行到accept()方法,就会处于等待状态不继续执行,一直到有客户端连接进来才会继续执行程序

  • recv():用于接收远程套接字对象发送的数据
    返回值:远程套接字发送的数据

  • sendall(data):用于向远程主机发送数据
    参数data:用于发送的数据

  • close():套接字的关闭方法,通信完毕之后,一定要记得关闭和服务器之间的TCP连接,释放资源。

2.2 TCP服务端程序编写

服务端程序开发,首先创建服务端程序的套接字对象,将套接字对象跟服务器IP地址和端口进行绑定;其次开始设置启动监听,等待客户端的连接;如果客户端一旦连接进来,就可以和客户端之间进行数据的收发操作;最后执行完成,关闭套接字

服务端程序开发流程

service.py代码如下:

import socket

# 创建服务端套接字
sc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定服务端IP地址和端口
sc.bind(("192.168.10.115", 8888))

# 开始监听
sc.listen(10)

# 等待连接
print("服务端程序启动完成,等待连接中...")
conn, addr = sc.accept()
print("客户端%s连接成功" % str(addr))

# 向客户端发送消息
conn.sendall("你好,客户端,我是服务器".encode("utf-8"))

# 关闭和这个客户端的套接字
conn.close()

运行上面的程序,我们会看到如下的等待界面:
服务端程序启动了
此时,我们通过telnet来访问以下这个ip和对应的端口,会发现服务器给我们发送了数据
telnet访问得到服务器发送的数据
同时我们运行的服务端也接收到了用户的请求
服务端接收到客户端的连接

2.3 TCP客户端程序编写

相对于服务端编程,客户端编程就变得比较简单了,我们通过 创建客户端套接字对象,通过调用套接字对象的connect(ip, port)方法连接指定ip和端口port的服务器,然后和服务器之间进行数据通信,通信完毕关闭客户端套接字。

客户端编程访问服务端程序

client.py代码如下:

import socket

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

sc.connect(("192.168.10.115", 8888))

msg = sc.recv(1024)
print("接收到服务器的欢迎消息:" + msg.decode("utf-8"))

sc.sendall("你好服务器".encode("utf-8"))

sc.close()

运行前面开发的服务器端程序

服务器程序启动成功
运行客户端程序,接收到服务器的数据:
客户端程序启动,接收到服务器发送的数据

以上,就是我们在进行TCP网络编程时的服务端编程和客户端编程的方式,下一节中我们使用TCP编程来开发一个简易的对讲机程序,实现服务端和客户端的数据通信


TCP实战

1. 简易对讲程序的需求

对讲机程序,就是双方互相通话的过程,简单一点的逻辑就是双方每次只能说一句话,然后等待对方回答之后继续说话。

2. 编程实现服务端

import socket

# 创建服务端套接字对象
service = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定主机和端口号
service.bind(("", 8888))

# 启动监听
service.listen(1)

# 接收客户端连接
print("服务端程序启动成功,等待客户端接入.....")
conn, addr = service.accept()
print("客户端已经接入,可以进行通信" + str(addr) + ";等待客户端发送消息...")

# 发送欢迎消息
conn.sendall("天王盖地虎,宝塔镇河妖".encode("utf-8"))

# 循环读取消息
while True:
    # 接收并打印客户端发送消息
    msg = conn.recv(1024)
    msg = msg.decode("utf-8")
    print("客户端:" + msg)
    # 如果客户端发送bye字符串,跳出循环
    if msg == "bye":
        service.sendall("over!")
        break;
    # 向客户端发送消息
    info = input("请输入要发送给客户端的消息:")
    info = info.encode("utf-8")
    conn.sendall(info)
# 关闭该客户端的连接
conn.close()

3. 编程实现客户端

import socket

# 创建客户端套接字对象
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接服务器
client.connect(("192.168.10.115", 8888))

# 循环处理发送消息
while True:
    # 接收服务器的消息
    msg = client.recv(1024)
    msg = msg.decode("utf-8")
    print("服务器:" + msg)
    # 如果一旦接收到over!字符串,跳出循环
    if msg=="over!":
        print("程序退出")
        break;
    # 给服务器发送消息
    info = input("请输入要发送的消息:")
    info = info.encode("utf-8")
    client.sendall(info)
#关闭客户端套接字对象
client.close()

4. 测试程序

首先运行服务端程序
服务端程序等待中
运行客户端程序
客户端程序启动
开始互相发送消息
服务端
服务端控制台界面
客户端
客户端控制台界面

整体效果如上所述,对于TCP网络编程的部分内容都有涉及,大家在独立完成的基础上,可以思考一个问题:怎么退出对话?!


  • 什么是UDP协议
  • UDP网络编程——服务端程序开发
  • UDP网络编程——客户端程序开发

1.什么是UDP协议

回顾TCP协议:一个非常重要的数据传输协议,很多网络协议都是以TCP协议为基础的;TCP协议要求服务器和客户端通过三次握手交互的方式建立可靠的连接,然后再进行数据保温的发送,在发送过程中保证数据包的顺序和数量不会丢失,最后如果要断开连接需要四次挥手的方式进行连接的安全断开。

UDP协议:是一种用户数据报协议,是一种非连接的协议,传输数据之前服务端和客户端之间不建立连接,当进行数据传送时就将应用程序中的数据提取出来并放在网络上;
发送端发送数据,只是收到当前应用程序生成数据的速度、计算能力和传输带宽等因素的影响
接收端接收数据,UDP将消息放在一个消息队列中,应用程序从消息队列中读取消息

UDP特性:
1、传输数据不建立连接,不需要维护连接状态,同一个服务端可以向多个客户端广播发送消息
2、UDP数据包标题8个字节,TCP需要20个字节,额外开销较小
3、UDP是不可靠的传输协议,不保证所有的数据接收端完整并且正确的接收
4、UDP协议是面向报文的,发送端UDP直接将程序中的数据封装成报文交给IP层进行传输,所以需要我们在程序中处理好报文数据的大小

关于TCP和UDP那点事儿
1、基于连接和非连接的
2、对系统资源的消耗多和少
3、TCP程序结构复杂、UDP程序结构简单明了
4、数据流模式的数据和数据报模式的数据
5、TCP是可靠的传输协议,UDP是不可靠的传输协议

2.UDP编程API简单了解

socket(family, type):用于表示网络连接的socket对象
family:socket.AF_INET用于表示使用IPv4地址
type:socket.SOCK_DGRAM表示使用数据报模式

s.bind((ip, port)):用于将套接字对象s和对应ip的主机及端口port绑定
注意:参数是一个元组

s.recvfrom(buffer):用于从socket中接收数据的方法
参数buffer:用于接收数据的缓冲区大小
返回值:得到客户端发送的消息和客户端的主机地址等信息

s.sendto(data, address):用于发送数据的方法
参数data:要发送的数据
参数address:数据发送的目的地地址

s.close()用于关闭套接字对象
使用完之后,一定要记得关闭网络套接字对象,释放系统资源哦

3. UDP服务端编程

和TCP网络编程一样,首先我们先开发服务端程序
服务端的程序开发步骤:首先创建表示网络传输的套接字对象socket();其次绑定对应的主机IP地址和端口号;接下来就可以进行消息的收发处理了;最后关闭套接字对象释放系统资源

UDP服务端编程

# 引入socket模块
import socket

# 创建socket对象
sc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 绑定主机端口
sc.bind(("", 9999))

# 开始收发消息
data = True
while data:
    # 接收客户端发送的消息
    data, addr = sc.recvfrom(1024)
    if "bye" == data.decode("UTF-8"):
        print("结束通话")
        break
    print("客户端发来消息:%s" % data.decode("UTF-8"))

    # 发送消息
    data = input("请输入要发送给客户端的消息:")
    sc.sendto(data.encode("UTF-8"), addr)

# 关闭套接字对象
sc.close()

4. UDP客户端编程

相对于服务端的编程,客户端编程非常简单,创建一个连接服务器的套接字对象,就可以直接进行数据收发处理了

UDP客户端编程处理

import socket
# 创建socket套接字对象
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 开始收发消息
data = input("请输入要发送给服务器的消息:")
while data:
    # 发送消息
    client.sendto(data.encode("UTF-8"), ("192.168.10.108", 9999))

    # 接收消息
    data, addr = client.recvfrom(2014)
    if "bye" == data.decode("UTF-8"):
        print("结束通话")
        break;
    print("服务器%s发来消息:%s" % (addr, data.decode("UTF-8")))
    data = input("请输入要发送给服务器的消息:")

# 关闭套接字对象
client.close()

运行上面的服务端程序和客户端程序,就可以实现服务端和客户端之间的数据通信了。和TCP不同的是,大家可以通过上面的程序进行测试,当服务端或者客户端一方的程序结束时,不会影响另一方的程序运行。

来源:http://www.jianshu.com/p/a5352fd65529
http://www.jianshu.com/p/2071c4990039
http://www.jianshu.com/p/6b182db8d1aa
http://www.jianshu.com/p/8451dccc25e3

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值