Python_socket

TCP 协议和 UDP 协议?

  • TCP(transfer control protocol): 传输控制协议,提供面向连接(TCP 的三次握手四次分手)、可靠的字节流服务;

  • UDP(user data protocol): 用户数据报协议,是一个简单的面向数据报的,无连接的运输层协议。

TCP 与 UDP 区别总结:

  1. TCP面向连接(如打电话要先拨号建立连接)
    UDP是无连接的,即发送数据之前不需要建立连接

  2. TCP 的传输是以数据流模式
    UDP 的传输是以数据报模式

  3. TCP 提供可靠的服务(通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达)
    UDP 尽最大努力交付,即不保证可靠交付

  4. UDP 具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信

  5. 每一条TCP连接只能是点到点的
    UDP 支持一对一,一对多,多对一和多对多的交互通信

  6. TCP 对系统资源要求较多
    UDP 对系统资源要求较少

TCP 的三次握手过程:
三次握手示意图:
在这里插入图片描述

  • 第一次握手:
    建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;
    SYN:同步序列编号(Synchronize Sequence Numbers)。

  • 第二次握手:
    服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

  • 第三次握手:
    客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

完成三次握手,客户端与服务器开始传送数据

为什么需要三次握手?

明明两次就可以建立连接的为什么还要加第三次的确认?

如果发送两次就可以建立连接话,那么只要客户端发送一个连接请求,服务端接收到并发送了确认,就会建立一个连接。

但是可能会出现问题:如果一个连接请求在网络中跑的慢,超时了,这时客户端会重发请求,但是这个跑的慢的请求最后还是跑到了,然后服务端就接收了两个连接请求,然后全部回应就会创建两个连接,导致浪费资源。

如果加了第三次客户端确认,客户端在接受到一个服务端连接确认请求后,后面再接收到的连接确认请求就可以抛弃不管了。

所以需要三次握手

TCP 的四次分手过程:

  • 客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送;
  • 服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1;
  • 服务器B关闭与客户端A的连接,发送一个FIN给客户端A;
  • 客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。

为什么分手需要四次?

因为 TCP 是双向的,所以需要在两个方向分别关闭,每个方向的关闭又需要请求和确认,所以一共需要4次。

什么是socket?

  • socket(ip:port):Unix ----> (Linux,IOS) ;
    一切皆文件 ----> socket也是一种特殊的文件;
    打开文件(open) ----> 读写(read/write) ----> 关闭文件(close)

  • socket模块:TCP/IP协议族的封装, 把应用层和TCP/IP协议族通信的中间软件抽象出来。

socket编程

scoket 编程的客户端 - 服务端工作方式示意图在这里插入图片描述

基于 TCP 的通信

TCP 工作方式示意图:
在这里插入图片描述
服务端:

import socket

# 1. 创建一个socket对象
# family指定使用IP协议的版本 -> IPV4:AF_INET,IPV6:AF_INET6
# type指定传输层使用的协议类型 -> TCP(SOCK_STREAM),UDP(SOCK_DGRAM)
server = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

# 2. 绑定一个IP和端口,供客户端来连接
server.bind(('172.25.254.67',5000))

# 3. 监听是否有客户端连接
server.listen(5)
print('服务端正在启动......')

# 4. 接收客户端的连接; accept() -> (socket object, address info)
clientSocket,clientAddress = server.accept()
print('客户端地址:',clientAddress)

# 5. 接收客户端发送的消息
recvData = clientSocket.recv(1024)
# 接收消息时,需要将消息decode解码为str类型
print('服务端接收的消息:',recvData.decode('utf-8'))

# 6. 给客户端回复消息; send()发送的消息需要encode编码成为bytes类型
clientSocket.send('你好,客户端!'.encode('utf-8'))

# 7.关闭socket对象
server.close()
clientSocket.close()

客户端:

import socket

# 1. 创建一个socket对象
client = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

# 2. 连接服务端
client.connect(('172.25.254.67',5000))

# 3. 给服务端回复消息
client.send('你好,服务端!'.encode('utf-8'))

# 4. 接收客户端发送的消息
recvData = client.recv(1024)
print('客户端接收的消息:',recvData.decode('utf-8'))

# 5.关闭socket对象
client.close()
基于 UDP 的通信

UDP 工作方式示意图:
在这里插入图片描述
服务端:

import socket

# 1. 实例化socket对象
udpServer = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)

# 2. 绑定IP和端口
# 0.0.0.0代表开放所有的IP地址
udpServer.bind(('0.0.0.0', 6000))
print('等待客户端UDP连接......')

# 3. 接收客户端的连接
recvData, address = udpServer.recvfrom(1024)
print('接收到客户端的数据:',recvData.decode('utf-8'))

# 4. 给客户端回复消息
udpServer.sendto(b'hello client',address)

# 5. 关闭socket对象
udpServer.close()

客户端:

import socket

udpClient = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)

udpClient.sendto(b'hello server', ('172.25.254.67', 6000))

recvData, address = udpClient.recvfrom(1024)
print('接收到服务端的数据:', recvData.decode('utf-8'))

udpClient.close()

启动服务端:
在这里插入图片描述
启动客户端,接收到服务端发送的消息,并给服务端发送一个消息:
在这里插入图片描述
返回服务端,接收到客户端发送的消息:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值