欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python使用套接字(socket)实现UDP与TCP通信

程序员文章站 2022-03-17 20:57:12
...

开放式系统互联模型

官方的模型分为七层,但在实际使用中大多数公司会把这个模型分为四层或者五层。
Python使用套接字(socket)实现UDP与TCP通信而在python建立一个简单的主机间的通信,我们需要了解IP、UDP与TCP

IP

相比IP对大多数人来说都并不陌生,IP是什么,在Windows下,我们可以通过ipconfig来查看自己的IP等相关网络配置,而在linux下我们可以通过ifconfig来查看自己的IP等相关信息

Windows环境下的ipconfig
Python使用套接字(socket)实现UDP与TCP通信Linux环境下的ifconfig
Python使用套接字(socket)实现UDP与TCP通信IP协议有两种,一种是我们当前较为常用的IPv4(inet),另一种是还在测试阶段,但也有越来越多的地方开始使用的IPv6(inet6),因为IPv4地址位数为32位(4个字节)与2019年11月26日被消耗殆尽,所以IPv6地址位数为128位(16个字节)作为下一代IP地址,已经开始在生活中随处可见了。点击查看你是否支持访问IPv6
端口

IP和端口是密不可分的,如果你想要让设备通信,不仅需要知道对方的IP还需要知道对方的开放了那些端口。假设我们要去到朋友家,我们可以把知道对方的家庭住址当成知道了对方的家,知道了对方的端口号就知道了对方家的门在哪,如果我们只是知道对方的家,却找不到门,我们照样无法和对方正常通信。
端口可以分为两种

  • 系统保留的端口: 0~1023
  • 动态端口: 1024~65535

系统保留的端口我们无法去调用,而在系统保留的端口中,我们要记住几个常用的端口

  • HTTP协议端口:80
  • HTTPS协议端口:443

套接字

套接字(socket):在应用层与传输层直接工作,可以说是套接字将应用层与传输层连接到了一起。它是计算机直接互相通信的一种约定方式。几乎所有可以网络编程的语言都支持套接字,Python当然也不例外。socket是Python的内置模块之一,无需下载即可使用

socket方法常用属性

family(协议族):

  • AF_INET(IPv4)
  • AF_INET6(IPv6)

type(套接字类型):

  • SOCK_STREAM(TCP协议)
  • SOCK_DGRAM(UDP协议)

UDP

UDP特点

  • 无需和对方建立连接即可发送数据
  • 可以一对一,一对多,多对多等多种模式
  • 系统资源占用小
    UDP是数据传输的一种方式,Python可以利用socket模块进行UDP的数据传输。
    UDP使用流程较为简单,而且对服务器(提供服务的一方)与客户端(被服务的一方)的区分并不大。

1.创建套接字
2.使用套接字收\发数据
3.关闭套接字
Python使用套接字(socket)实现UDP与TCP通信

UDP发送数据

发送数据默认只能发送ASCII编码的数据,且发送的数据必须是字节类型,所以我们可以用.encode()方法改变字节编码,在Windows系统中使用的是gbk的编码,如果你使用的电脑是Mac或者Linux系统,发送的数据使用utf-8则不会乱码

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import socket

def send_main():
    # family(协议族):AF_INET(IPv4) AF_INET6(IPv6) type(套接字类型) SOCK_STREAM(TCP协议) SOCK_DGRAM(UDP协议)
    udp_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
    # 使用.sendto方法向指定ip的端口发送数据
    send_data = '数据'
    udp_socket.sendto(send_data.encode('gbk'), ('127.0.0.1', 12821))
    # 关闭UDP
    udp_socket.close()

if __name__ == '__main__':
    send_main()

UDP接收数据

接收数据,我们需要用到.bind()方法绑定地址,.recvfrom方法来接收数据并且设置接收的最大字节数(默认:1024)
.bind()方法:需要传入一个元组进入,元组内放入ip与端口,端口号需要为int类型。ip可以为空,当ip为空时,会默认为所以本地ip。例`udp_socket.bind((’’, 1024))

def rece_main():
    udp_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
    udp_socket.bind(('', 12822))
    print(udp_socket.recvfrom(1024))

使用.recvfrom()方法接收的数据为数组格式:(字节数据,(发送IP,发送端口))。
如: (b’\xca\xfd\xbe\xdd’, (‘127.0.0.1’, 12821)),我们可以取出其中的字节使用.decode()方法进行转换。

TCP

TCP特点

面向连接

  • 通信双方必须先建立连接才能进行数据的传输
  • 可靠传输

TCP采用发送应答机制

  • 超时重传
  • 错误校验
  • 流量控制和阻塞管理

TCP在客户端和服务端上有着较为明显的区别
Python使用套接字(socket)实现UDP与TCP通信

TCP客户端

TCP在创建套接字时,使用的的type(套接字类型)为SOCK_STREAM。

  • 使用.connect()方法连接服务器
  • 使用.send()方法发送数据,.recv()方法接收数据,默认最大接收1024个字节(.encode()方法用于设定二进制文件的编码格式,默认为ascll不支持中文格式)
  • 使用.close()方法断开连接
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def tcp_send_client():
    """使用tcp发送数据"""
    # 创建tcp套接字
    tcp_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
    # 连接服务器
    tcp_socket.connect(('127.0.0.1', 12823))
    # 发送数据
    data = '数据'
    tcp_socket.send(data.encode('gbk'))
    # 断开连接
    tcp_socket.close()

def tcp_recv_client():
    """使用tcp接收数据"""
    # 创建TCP套接字
    tcp_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
    # 连接服务器
    tcp_socket.connect(('127.0.0.1', 12823))
    # 接收数据
    data = tcp_socket.recv(1024)
    # 打印数据
    print(data.decode('gbk'))
    # 断开连接
    tcp_socket.close()

TCP服务端

服务端主要用到的方法

  • .bind()方法绑定端口
  • .listen()方法将主动转为被动(可以理解为设置为接听模式,方法中传入的数值将影响能同时连接的主机数量,能同时连接的数量同时还会受到系统的影响)
  • .accept()方法,创建连接副本,并且返回连接主机的信息(TCP不同于UDP的可以一对多,TCP只能为一对一的连接方式,但是这里采用了一个解决方案可以让多个主机同时连接,每次连接时候都会创建一个TCP副本,将连接指向副本,这样就可以进行多个连接)
  • .recv()与.send()方法接收数据与发送数据时需要对.accept()创建的副本进行操作,如果直接对socket方法创建的套接字操作会出现不可预知的错误
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def tcp_recv_server():
    """服务端接收数据"""
    # 创建tcp套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 绑定信息
    tcp_server.bind(('127.0.0.1', 12824))
    # 将主动转被动(服务器提供连接服务时需要)
    tcp_server.listen(128)
    # 等待连接(接到连接后,会创建一个连接副本,然后返回连接到此端口的主机信息)
    new_tcp, host_info = tcp_server.accept()
    # 接收数据
    data = new_tcp.recv(1024).decode('gbk')
    print(data)


def tcp_send_server():
    """服务端发送数据"""
    # 创建tcp套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 绑定信息
    tcp_server.bind(('127.0.0.1', 12824))
    # 将主动转被动(服务器提供连接服务时需要)
    tcp_server.listen(128)
    # 等待连接(接到连接后,会创建一个连接副本,然后返回连接到此端口的主机信息)
    new_tcp, host_info = tcp_server.accept()
    # 发送数据
    data = 'TCP数据'
    new_tcp.send(data.encode('gbk'))

TCP和UDP的区别

  • TCP面向连接;UDP是无连接的,即发送数据之前不需要建立连接。
  • TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。
  • UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
  • 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。
  • TCP对系统资源要求较多,UDP对系统资源要求较少。
  • TCP的客服端与服务端区别较大,UDP客户端与服务端区别较小
相关标签: python