【Python网络编程】TCP和UDP的使用(附实例)

一、网络编程

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

举个例子,当你使用浏览器访问新浪网时,你的计算机就和新浪的某台服务器通过互联网连接起来了,然后,新浪的服务器把网页内容作为数据通过互联网传输到你的电脑上。

由于你的电脑上可能不止浏览器,还有QQ、Skype、Dropbox、邮件客户端等,不同的程序连接的别的计算机也会不同,所以,更确切地说,网络通信是两台计算机上的两个进程之间的通信。比如,浏览器进程和新浪服务器上的某个Web服务进程在通信,而QQ进程是和腾讯的某个服务器上的某个进程在通信。网络编程对所有开发语言都是一样的,Python也不例外。用Python进行网络编程,就是在Python程序本身这个进程内,连接别的服务器进程的通信端口进行通信。

因为互联网协议包含了上百种协议标准,但是最重要的两个协议是TCP和IP协议,所以,TCP编程和UDP编程是最主要的两种网络类型的编程。

二、Socket的定义

Socket又称 ‘套接字’,是网络编程的一个抽象概念。通常我们用一个Socket表示 ‘打开了一个网络链接’,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可。应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

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

三、连接过程

根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。

1)服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。

2)客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

3)连接确认:当服务器端套接字监听到或者接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。此时服务器端的套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

四、基于TCP协议的Socket编程

大多数连接都是可靠的TCP连接。创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器。

TCP协议则是建立在IP协议之上的。TCP协议负责在两台计算机之间建立可靠连接,保证数据包按顺序到达。TCP协议会通过三次握手建立连接,然后,对每个IP包编号,确保对方按顺序收到,如果包丢掉了,就自动重发。许多常用的更高级的协议都是建立在TCP协议基础上的,比如用于浏览器的HTTP协议、发送邮件的SMTP协议等。

一个TCP报文除了包含要传输的数据外,还包含源IP地址和目标IP地址,源端口和目标端口。

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

  • 基于TCP协议的Socket通信流程

下面用实例来帮助大家理解基于TCP协议的socket通信过程。该程序由客户端远程向服务器端发送命令,服务器端执行并且将执行结果发给客户端。

  • 服务器
#TCP服务器编程  
import socket              #导入 socket 模块
import os 

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)   #创建一个socket
s.bind(('0.0.0.0',1000))   #绑定地址(host,port)到套接字,在AF_INET下,以元组(host,port)的形式表示地址。
s.listen(5)                #调用listen方法开始监听端口,传入的参数为操作系统可以挂起的最大连接数量,一般设为5

sock,addr=s.accept()       #被动接受TCP客户端连接,等待连接的到来
for i in range(10):
    cmd = sock.recv(1024)  #接收TCP数据,数据以字符串形式返回;'1024'表示每次接收的最大数据量
    print(cmd)
    command = cmd.decode()

    if command.startswith("cd"):        #远程控制不能执行cd命令,需单独处理
        os.chdir(command[2:].strip())   #切换路径
        result=os.getcwd()              #显示路径
    elif command=='exit':               
        break 
    else:
        result=os.popen(command).read() #如果接收的命令不是以'cd'开头的,则直接执行命令

    if result:    
        sock.send(result.encode())      #如果执行的结果有返回值,则将结果返回给客户端
    else:
        sock.send(b'OK!')               #如果执行的结果无返回值,则给客户端发送'OK'

s.close()                               #关闭连接
  • 客户端
#TCP客户端编程--socket  作者:成纤纤
import socket                  #导入socket模块
import os

s=socket.socket()              #创建一个socket对象
s.connect(("127.0.0.1",1000))  #主动初始化TCP服务器连接,一般以元组(host,port)的形式表示地址。
for i in range(10):
    com=input("输入命令:")
    if com=='exit':            
        s.send(b'exit')        #发送TCP数据,将输入的命令发送到连接的套接字。
        break
    else:
        s.send(com.encode())        

    d=s.recv(65536)                 #接收TCP数据,数据以字符串形式返回;'65536'为指定要接收的最大数据量。
    print(d.decode(),'--->',len(d)) #打印从服务端发送回来的数据和长度
    
s.close()                           #关闭连接
  • 运行结果:

对于服务器,要首先监听指定端口,然后,对每一个新的连接,创建一个线程或进程来处理。通常,服务器程序会无限运行下去。对于客户端,要主动连接服务器的IP和指定端口。所以我们在运行程序时,需先运行服务器端的程序,然后在运行客户端的程序,否则客户端的程序会报错。通俗一点来说,只有当目标主机(服务器端)活跃时,我们(客户端)才能连接它。

同一个端口,被一个Socket绑定了以后,就不能被别的Socket绑定了。

看完这个例子,大家有没有注意到,当我们接收数据时,需要调用decode()方法,发送数据时,需要调用encode()方法。这是为什么呢?

encode()和decode()都是字符串的函数,从英文意思上看,encode和decode分别指编码和解码,默认格式为UTF-8。数据在物理层上是以字节流(bytes)的形式传输的,所以在发送消息时,我们需要对字符串进行编码,获得bytes类型对象;接收数据时,就需要对其进行解码。

五、基于UDP协议的Socket编程

  • 基于UDP协议的Socket通信流程

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

对于基于UDP协议的Socket通信,服务器不需要调用listen()方法,而是直接接收来自任何客户端的数据。

下面的UDP编程实现的是一个简单的聊天过程!

  • 服务器
#UDP服务器
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  #创建一个socket
s.bind(("127.0.0.1",9999))               #绑定端口
while 1:
    #recvfrom()方法返回数据和客户端的地址与端口,这样,服务器收到数据后,直接调用sendto()就可以把数据用UDP发给客户端。 
    sock,addr=s.recvfrom(1024)   
    message=sock.decode()
    print(message,addr)
    if message=='exit':                    #客户端先结束对话
        break
  
    data=input("I:")
    s.sendto(data.encode(),addr)           #从把数据从接收数据的端口发送出去
s.close()
  • 客户端

客户端使用UDP时,首先仍然创建基于UDP的Socket,然后,不需要调用connect()方法,直接通过sendto()给服务器发数据:

#UDP客户端(访问端)
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  #创建一个socket对象
while 1:
    #发送数据
    message=input("I:")
    s.sendto(message.encode(),("127.0.0.1",9999))   
    if message=='exit':
        break
    #接收数据
    sock,addr=s.recvfrom(1024)   
    print(sock.decode(),addr)
s.close()
  • 运行结果:

小结: UDP的使用与TCP类似,但是不需要建立连接。此外,服务器绑定UDP端口和TCP端口互不冲突,也就是说,UDP的9999端口与TCP的9999端口可以各自绑定。
**## 学习资源推荐

除了上述分享,如果你也喜欢编程,想通过学习Python获取更高薪资,这里给大家分享一份Python学习资料。

这里给大家展示一下我进的兼职群和最近接单的截图

兼职群

私单

😝朋友们如果有需要的话,可以V扫描下方二维码联系领取,也可以内推兼职群哦~

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

### 1.Python学习路线

image-20230619144606466

python学习路线图1

2.Python基础学习
01.开发工具

02.学习笔记

在这里插入图片描述

03.学习视频

在这里插入图片描述

3.Python小白必备手册

图片

4.数据分析全套资源

在这里插入图片描述

5.Python面试集锦
01.面试资料

在这里插入图片描述

在这里插入图片描述

02.简历模板

在这里插入图片描述

因篇幅有限,仅展示部分资料,添加上方即可获取👆

------ 🙇‍♂️ 本文转自网络,如有侵权,请联系删除 🙇‍♂️ ------

**

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值