1、套接字
进程通信的接口。
可以看做对 TCP/IP协议的封装。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,
TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。
2、目的
通过编程语言提供的套接字编程接口,可以更简单的完成基于tcp和udp的编程
3、套接字类别
【1】流式套接字(SOCK_STREAM):
传输层基于tcp的协议通信, 面向连接可靠的传输
【2】数据报套接字(SOCK_DGRAM):
传输层基于udp协议传输 ,面向无连接不可靠的传输
【3】底层套接字 (SOCK_RAM): 访问底层协议套接字
4、tcp粘包
【1】产生原因:
① tcp传输以字节流的方式发送消息,消息之间没有边界,每次收发有大小限制
② 发送比接受的速度快
【2】影响 : 对每次发送的内容是一个独立的意思需要单独识别
【3】如何处理:
① 每次发送后加一个结尾标志
② 发送一个数据结构
③ 每次发送有一个间隔
5、tcp流式套接字和udp数据报套接字区别
【1】 流式套接字采用字节流方式进行传输,而数据报套接字 使用数据报形式传输数据
【2】 tcp套接字会产生粘包,udp不会
【3】 tcp编程可以保证消息的完整性,udp则不能保证
【4】 tcp需要listen accept,udp不用
【5】 tcp消息的发送接收使用recv send sendall,udp使用 recvfrom,sendto
6、套接字编程应用--TCP
【1】服务端:
① 创建套接字对象
sock = socket.socket(sock_family = AF_INET, sock_type = SOCK_STREAM, proto = 0)
参数 : sock_family,地址族类型 ,通常为AF_INET,表示 ipv4网络通信
sock_type, 套接字类型, SOCK_STREAM,表示流式套接字。 SOCK_DGRAM,表示数据报套接字
proto, 通常为0,表示选定的子协议类型
功能 : 创建套接字
返回值 : 返回套接字对象
② 绑定地址
sock.bind(addr)
参数 : addr,(ip,port)组成的一个元组 ('0.0.0.0',1234)
功能 : 绑定地址
③ 设置监听套接字
sock.listen(n)
参数: 监听队列大小
功能: 将套接字设置为监听套接字,创建监听队列
* 一个监听套接字可以连接多个客户端
④ 等待接受客户端连接
connfd,addr = sock.accept()
功能 : 阻塞等待处理客户端连接
返回值 : connfd 新的套接字,用于和客户端通信
addr 连接的客户端的地址 (ip,port)
* 阻塞函数 : 当程序运行到阻塞函数位置,如果某种条件没有达成则暂停程序运行,直到条件达成结束阻塞
⑤ 消息的收发
接收消息:
data = connfd.recv(buffersize)
参数 : 一次接受消息的大小 ,为字节
功能 : 接受消息
返回值 : 返回接受到的内容
发送消息:
n = connfd.send()
参数 : 要发送的内容 (bytes格式)
功能 : 发送消息
返回值 : 返回实际发送的字节数
⑥ 关闭套接字
sock.close()
【客户端】
① 创建套接字对象 (和服务端套接字类型相同)
sock = socket.socket(sock_family = AF_INET, sock_type = SOCK_STREAM, proto = 0)
② 发起连接 connect(addr)
)
参数 : 服务端地址,是一个元组(ip,port) # 服务端绑定的地址
功能 : 向服务端发起连接
③ 消息收发
发送消息:
"Msg>>")
sock.send(msg.encode())
接收消息:
1024) # recv方法参数,一次接收数据的大小
print(data)
④ 关闭套接字
sock.close()
7、套接字编程应用-UDP
【服务端】
① 创建套接字对象
sock = socket(AF_INET,SOCK_DGRAM)
② 绑定地址
sock.bind()
③ 消息收发
【接收消息】:
data,addr = sock.recvfrom(buffersize)
功能: 接受UDP消息
参数: 每次最多接受消息的大小, 字节
返回值:data, 接收到的内容
addr, 消息发送方的地址
* recvfrom每次接收一个报文,如果没有接收完全则丢弃没有收到的内容
【发送消息】:
sock.sendto(data,addr)
功能: UDP消息发送
参数: data, 要发送的内容 ,bytes
addr 目标地址
返回值:发送字节数
④ 关闭套接字
sock.close()
【客户端】
① 创建套接字对象
sock = socket(AF_INET,SOCK_DGRAM)
② 消息收发
【给服务端发送消息】
sock.sendto(data.encode(),ADDR)
# data,要发送的数据
# ADDR,服务端地址(ip,port)
【接收服务端返回的消息】
1024)
③ 关闭套接字
sock.close()