Python 笔记02 (网络交互 TCP/UDP)
最佳答案 问答题库548位专家为你答疑解惑
一 socket网络及差别介绍
TCP(传输控制协议)和UDP(用户数据报协议)是两种常见的互联网传输协议,它们之间有很多区别,包括以下几个主要方面:
1.1 TCP
TCP是传输控制协议,是面向连接的通讯协议(如:打电话),通过三次握手建立连接,通讯完成时四次挥手,一般应用在对安全性、完整性有严格要求的场景,如FTP、SMTP、HTTP等
- 优点:TCP 具有高可靠性,确保传输数据的正确性,不出现丢失或乱序
- 缺点:TCP相对于UDP速度慢一点,效率低,而且要求系统资源较多,每个连接都会占用系统的CPU、内存等硬件资源
1.2 UDP
UDP是用户数据报协议,是面向无连接的通讯协议(如:发短信)
- 优点:UDP速度快、操作简单、要求系统资源较少
- 缺点:不可靠,可能会出现丢包、乱序、数据不完整
1.3 TCP 与 UDP 的区别:
- 连接 TCP 是面向连接的传输层协议,传输数据前先要建立连接。UDP 是不需要连接,即刻传输数据。
- 服务对象 TCP 是一对一的两点服务,即一条连接只有两个端点。UDP 支持一对一、一对多、多对多的交互通信
- 可靠性 TCP 是可靠交付数据的,数据可以无差错、不丢失、不重复、按序到达。UDP 是尽最大努力交付,不保证可靠交付数据。
- 拥塞控制、流量控制 TCP 有拥塞控制和流量控制机制,保证数据传输的安全性。UDP 则没有,即使网络非常拥堵了,也不会影响 UDP 的发送速率。
- 首部开销 TCP 首部长度较长,会有一定的开销,首部在没有使用「选项」字段时是 20 个字节,如果使用了「选项」字段则会变长的。UDP 首部只有 8 个字节,并且是固定不变的,开销较小,对系统资源要求较少。
- 实时性 UDP 具有较好的实时性,工作效率比 TCP 协议高。
1.4 应用场景
- 由于 TCP 是面向连接,能保证数据 的可靠性交付,因此经常用于:(20/21端口)FTP 文件传输、HTTP / HTTPS(80端口) 、SMTP(简单邮件传送协议)、TELNET(远程终端协议)
- 由于 UDP 面向无连接,它可以随时发送数据,再加上UDP本身的处理既简单又高效,因此经常用于:包总量较少的通信,如 DNS 、SNMP、TFTP(简单文件传输协议) 等、视频、音频等多媒体通信、广播通信
1.5 Socket数据传输方式
常用的有两种:
- SOCK_STREAM:表示面向连接的数据传输方式。数据可以准确无误地到达另一台计算机,如果损坏或丢失,可以重新发送,但效率相对较慢。常见的 http 协议就使用 SOCK_STREAM 传输数据,因为要确保数据的正确性,否则网页不能正常解析。针对于面向连接的TCP服务应用;
- SOCK_DGRAM:表示无连接的数据传输方式。计算机只管传输数据,不作数据校验,如果数据在传输中损坏,或者没有到达另一台计算机,是没有办法补救的。也就是说,数据错了就错了,无法重传。因为 SOCK_DGRAM 所做的校验工作少,所以效率比 SOCK_STREAM 高。对应于无连接的 UDP服务应用。
1.6 服务器端
from socket import *
server = socket(AF_INET, SOCK_DGRAM)
server_host_port = ('127.0.0.1', 6000) # 服务器的IP地址和端口# 接收数据前绑定端口
server.bind(server_host_port)while True:# 接收数据data = server.recvfrom(1024)# print('data:', data) # (b'\xe4\xbd\xa0\xe5\xa5\xbd', ('127.0.0.1', 61328))print('访问者:', data[0].decode('utf-8')) # 你好# print(f'客户端的IP:{data[1][0]} \n客户端的端口:{data[1][1]}')"""重新发送数据"""send_data = input('客服说:')server.sendto(send_data.encode('utf-8'), data[1])# server.close()
1.7 客户端
from socket import *
client = socket(AF_INET, SOCK_DGRAM)
server_host_port = ('127.0.0.1', 6000) # 指定数据接收方while True:data = input('访问者:')data = data.encode('utf-8')client.sendto(data, server_host_port) # 发送数据if data.decode('utf-8') == 'bye':break"""接收返回数据数据"""recv_data = client.recvfrom(1024)print(f"客服说:{recv_data[0].decode('utf-8')}")print('程序关闭')
client.close()
二 UDP协议
udp的交互使用:sendto 和 recvfrom
SOCK_DGRAM:表示无连接的数据传输方式。计算机只管传输数据,不作数据校验,如果数据在传输中损坏,或者没有到达另一台计算机,是没有办法补救的。也就是说,数据错了就错了,无法重传。因为 SOCK_DGRAM 所做的校验工作少,所以效率比 SOCK_STREAM 高。对应于无连接的 UDP服务应用。
2.1 服务器代码
from socket import *
import struct
server_socket = socket(AF_INET, SOCK_DGRAM)host_port = ('localhost', 8888) # 端口号# 开始监听
server_socket.bind(host_port)# 接收数据
data = server_socket.recvfrom(1024)
print(data, type(data))# 解析操作码
recv_data = data[0]
new_data = struct.unpack('!H', recv_data[:2])
print('客户端请求的操作码:', new_data)# 解析文件名
file_name = recv_data[2:-7].decode('utf-8')
print('客户端请求下载的文件名:', file_name)
server_socket.close()
2.2 客户端代码
from socket import *
import struct
client_socket = socket(AF_INET, SOCK_DGRAM)host_port = ('localhost', 8888) # 端口号file_name = input('请输入需要上传的文件名:').encode('utf-8')
print('file_name:', file_name, len(file_name))
data = struct.pack('!H%dsb5sb' % len(file_name), 1, file_name, 0, 'octet'.encode('utf-8'), 0)# 发送数据
client_socket.sendto(data, host_port)
client_socket.close()
三 TCP协议
tcp的交互使用:send 和 recv
SOCK_STREAM:表示面向连接的数据传输方式。数据可以准确无误地到达另一台计算机,如果损坏或丢失,可以重新发送,但效率相对较慢。常见的 http 协议就使用 SOCK_STREAM 传输数据,因为要确保数据的正确性,否则网页不能正常解析。针对于面向连接的TCP服务应用;
3.1 TCP服务器代码
from socket import *
import random# 创建SOCKET对象
server_socket = socket(AF_INET, SOCK_STREAM)# 绑定IP和端口
host_port = ('', 6666) # 不写本机所有
server_socket.bind(host_port)# 设置listen
server_socket.listen(5)while True:# 等待客户端连接client_socket, addr = server_socket.accept()print('客户端已连接,3次握手完成! ')# print('client_socket:', client_socket)# 接收数据data = client_socket.recv(1024).decode('utf8')print('data:', data)oper_code = data.split(':')[0] # 操作码recv_data = data.split(':')[1] # 需要上传和下载的文件if oper_code == '1': # 下载操作file_read = open(recv_data, 'r', encoding='utf8')data = file_read.read()# 将数据发给客户端client_socket.send(data.encode('utf-8'))file_read.close()elif oper_code == '2': # 上传操作file_write = open(str(random.randint(1000, 9999)) + '.txt', 'w', encoding='utf-8')file_write.write(recv_data)file_write.close()print('服务器接收完成!')elif oper_code == '0': # 已退出print(recv_data)
3.2 客户端代码
from socket import *while True:client_socket = socket(AF_INET, SOCK_STREAM)# 指定要连接的IPhost_port = ('127.0.0.1', 6666)# 开始连接服务器client_socket.connect(host_port)choice = eval(input('请选择操作: 0.退出 1.下载 2.上传 \n'))if choice == 1:file_name = input('请输入要下载的文件名:')# 告诉服务器要下载的文件名join_data = (str(choice) + ':' + file_name).encode('utf-8')# 发送数据client_socket.send(join_data)# 接收服务器返回的数据recv_data = client_socket.recv(1024).decode('utf-8')# 写入本地磁盘download = open(file_name, 'w', encoding='utf-8')download.write(recv_data)download.close()print('下载完成')elif choice == 2: # 上传path_name = input('请输入要上传的文件名:')# 本地读取upload = open(path_name, 'r', encoding='utf-8')upload_data = upload.read()# 拼接数据结构data = (str(choice) + ':' + upload_data).encode('utf-8')# 向服务器发送数据client_socket.send(data)upload.close()print('数据上传成功!')elif choice == 0:# 告诉服务器已退出client_socket.send((str(choice) + ':' + '客户端已退出').encode('utf-8'))breakprint('客户端关闭')
TCP连接时三次握手:
-
第一次:客户端向服务器端发送连接报文(SYN=1),同时选择一个初始序列号 seq=x,一起发送
-
第二次:服务器收到报文后向客户端发报文,确认报文为:(ACK=1,SYN=1),确认号为ack=x+1,同时服务器初始化一个序列号:seq=y,一起发送
-
第三次:客户端向服务器端发送报文(ACK=1),同时发送:ack=x+1,seq=y+1进行确认
TCP断开时四次挥手:开时四次挥手:
-
第一次:客户端发送释放报文并停止发送数据(FIN=1),带上序列号 seq=u,客户端进入终止等待状态(FIN-WAIT-1)
-
第二次:服务器收到报文后释放报文,发出确认报文(ACK=1,ack=u+1),并且带上序列号 seq=v,服务器进入关闭等待状态(CLOSE-WAIT)
-
第三次:服务器在数据传输完毕后发送连接释放报文(FIN=1,ack=u+1),同时发送序列号:seq=w,服务器进入最后确认状态(LAST-ACK)
-
第四次:客户端收到释放报文后,向服务器发送报文(ACK=1,ack=w+1),发送序列号 seq=u+1,客户端进入时间等待状态(TIME-WAIT)。服务器接收到报文后直接关闭,客户端需要等2**MSL(最长报文段寿命)后结束
99%的人还看了
相似问题
猜你感兴趣
版权申明
本文"Python 笔记02 (网络交互 TCP/UDP)":http://eshow365.cn/6-13318-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!
- 上一篇: 可变性隔离
- 下一篇: 【算法】排序——插入排序及希尔排序