python网络通信效率_Python 网络编程之 UDP 协议

UDP 和 TCP 的区别

TCP

UDP

连接性

面向连接

面向无连接

传输可靠性

可靠

不可靠

传输模式

数据报

应用场景

传输大量的数据

少量数据

速度

TCP:

TCP 的可靠体现在传输数据之前,会有三次握手来建立连接。在数据传完后,还会断开连接用来节约系统资源。在数据传递时,有确认机制、重传机制、拥塞控制机制以保证传输的可靠性,但这些机制都会消耗大量的时间和系统资源,每个连接都会占用系统的 CPU、内存等硬件资源,所以也导致 TCP 容易被人利用,比如 DDOS、CC 等攻击。

一般用于文件传输、收发邮件或远程登录等对数据准确性要求高的场景。

UDP:

UDP 没有 TCP 那些可靠的机制,所以在数据传递时,如果网络质量不好,就会很容易丢包。但 UDP 也是无法避免攻击的,比如:UDP Flood 攻击。

一般用于即时通讯、在线视频、网络电话等对传输效率要求高,但对准确性要求相对低的场景。

面向有连接型

bVbbnY9?w=410&h=199

发送数据之前,需要在收发主机之间建立一条通信线路,在通信传输前后,专门进行建立和断开连接的处理,如果与对端之间无法通信,可避免发送无谓的数据。

面向无连接型

bVbbnZl?w=407&h=195

这种类型不要求建立和断开连接,发送端可任何时候发送数据,接收端也不知道自己何时从哪里接受数据,这种情况下,接收端需要时常确认是否收到数据,彼此也不需要确认对方是否存在。

关于 TCP 网络编程的实现请参考我的另一篇博文 Socket 通信原理

UDP 网络编程实现

面向无连接的 UDP 时序图

bVbbn07?w=464&h=396

创建 Socket

sock = socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)

family -> 地址族

socket.AF_UNIX: 用于同一台机器上的进程通信(既本机通信)

socket.AF_INET: 用于服务器与服务器之间的网络通信

socket.AF_INET6: 基于 IPV6 方式的服务器与服务器之间的网络通信

type -> Socket 对象的类型

socket.SOCK_STREAM: 基于 TCP 的流式 Socket 通信

socket.SOCK_DGRAM: 基于 UDP 的数据报式 Socket 通信

socket.SOCK_RAW: 原始套接字,普通的套接字无法处理 ICMP、IGMP 等网络报文,而 SOCK_RAW 可以;其次 SOCK_RAW 也可以处理特殊的 IPV4 报文;此外,利用原始套接字,可以通过 IP_HDRINCL 套接字选项由用户构造 IP 头

socket.SOCK_SEQPACKET: 可靠的连续数据包服务

proto -> 协议编号,默认是 0,一般可以忽略该参数

fileno -> Socket 的文件描述符,如果指定了 fileno,则其他参数将被忽略,返回指定文件描述符的 Socket。

创建 TCP Socket:

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

创建 UDP Socket:

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

UDP 通信

sock.recvfrom(bufsize[, flags])

接受 UDP 套接字的数据,与 recv() 类似,但返回值是 tuple(data, address)。其中 data 是包含接受数据的字符串,address 是发送数据的 Socket 地址

注意协议接收到的数据可能大于 buf 的长度,所以在这种情况下要调用几次 recv 函数才能把 Socket 接收缓冲区中的数据 copy 完。recv 函数仅仅是 copy 数据,真正接收数据是由协议来完成的。

sock.sendto(bytes, address)

发送 UDP 数据,将数据发送到 Socket,address 形式为 tuple(ipaddr, port),指定远程地址发送,返回值是发送的字节数

Python 2.x 发送的报文是 str 类型,Python 3.x 发送的报文是 bytes 类型,在发送前要记得编码。

客户端代码

import socket

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

address = ('127.0.0.1', 8020)

while True:

msg = input('Wanna send: ')

if not msg:

break

sock.sendto(bytes(msg, 'utf-8'), address) # Return the number of bytes sent

data, addr = sock.recvfrom(1024)

data = data.decode('utf-8')

print('Response:', data)

sock.close()

服务端代码

import socket

import time

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

sock.bind(('127.0.0.1', 8020))

print('waiting for message...')

while True:

data, addr = sock.recvfrom(1024)

data = data.decode('utf-8')

print('Got message from', addr)

print('Received message:', data)

sock.sendto(bytes('[%s] %s' % (time.ctime(), data), 'utf-8'), addr)

sock.close()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值