TCP | UDP | |
---|---|---|
链接性 | 面向链接 | 面向无链接 |
传输可靠性 | 可靠 | 不可靠 |
传输模式 | 流 | 数据报 |
应用场景 | 传输大量的数据 | 少许数据 |
速度 | 慢 | 快 |
TCP:python
TCP 的可靠体如今传输数据以前,会有三次握手来创建链接。在数据传完后,还会断开链接用来节约系统资源。在数据传递时,有确认机制、重传机制、拥塞控制机制以保证传输的可靠性,但这些机制都会消耗大量的时间和系统资源,每一个链接都会占用系统的 CPU、内存等硬件资源,因此也致使 TCP 容易被人利用,好比 DDOS、CC 等攻击。编程
通常用于文件传输、收发邮件或远程登陆等对数据准确性要求高的场景。segmentfault
UDP:服务器
UDP 没有 TCP 那些可靠的机制,因此在数据传递时,若是网络质量很差,就会很容易丢包。但 UDP 也是没法避免攻击的,好比:UDP Flood 攻击。网络
通常用于即时通信、在线视频、网络电话等对传输效率要求高,但对准确性要求相对低的场景。socket
- 面向有链接型
发送数据以前,须要在收发主机之间创建一条通讯线路,在通讯传输先后,专门进行创建和断开链接的处理,若是与对端之间没法通讯,可避免发送无谓的数据。函数
- 面向无链接型
这种类型不要求创建和断开链接,发送端可任什么时候候发送数据,接收端也不知道本身什么时候从哪里接受数据,这种状况下,接收端须要时常确认是否收到数据,彼此也不须要确认对方是否存在。编码
关于 TCP 网络编程的实现请参考个人另外一篇博文 Socket 通讯原理spa
面向无链接的 UDP 时序图code
建立 Socket
sock = socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
family -> 地址族
type -> 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()