socket模块
socket模块
socket层
1.理解socket
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
从自己的角度看,socket就是一个模块,通过调用模块可以建立两个进程之间的连接和通信。也有人将socket模块看成IP+PORT,通过IP可以找到一台主机的位置,而通过端口PORT可以找到电脑上的一个应用程序,并通过socket模块实现网络通信,达到跨主机通信。
1、socket模块基本使用
1.socket模块,也叫套接字
2.历史
起源于20世纪70年代加利福尼亚大学伯克利分校版本的Unix,即人们所说的BSD Unix.所以套接字也称为‘伯克利套接字’或者‘BSD’套接字。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。
基于文件类型的套接字家族
套接字家族的名字:AF_UNIX
unix一切皆文件,基于文件的套接字调用的就是底层的文件 系统来取数据,两个套接字进程运行在同一机器,可以通过访问 同一个文件系统间接完成通信
基于网络类型的套接字家族
套接字家族的名字:AF_INET
(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不 过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)
1.使用流程
TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。
UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。
socket模块的基本使用
1.socket.socket() 产生socket对象
2.bind() 绑定地址
3.listen() 半连接池
4.accept() 等待客户端链接
5.send() 发送消息
6.recv() 接收消息
7.connect() 链接服务端
流程图如下:
2、代码初体验
服务端
import socket
# 1.产生一个socket 对象并指定采用的通信版本和协议(TCP)
server = socket.socket() # 括号内不写参数,默认就是TCP协议 family = AF_INET基于网路的套接字,type = SOCK_STREAM流式协议即TCP
# 2.绑定一个固定的地址(服务端必备的条件)
server.bind(('127.0.0.1',8080)) # 127.0.0.1 为本地回环地址,只有自己的电脑可以访问
# 3.设立半连接池(当超过5个客户端来访问时,前五个在排队等待,第六个之后的客户端会报错,当前面一个客户端退出了,第六个客户端就会顶替掉)
server.listen(5)
# 4.等待客户端
sock,addr = server.accept() # return sock,addr 三次握手就会返回
print(sock,addr) # sock就是双向通道,addr就是客户端地址
# 5.服务客户端
data = sock.recv(1024) # 接收客户端发送过来的消息 ,1024字节
print(data.decode('utf8')) # 结果是二进制需要解码
sock.send('尊敬的客人 ,一切随你的要求'.encode('utf8')) # 客户端发送消息,注意消息必须是bytes类型
#6.关闭双向通道
sock.close() # 四次挥手
# 7.关闭服务端
server.close() # 本次服务结束了
客户端
import socket
#1.生成socket对象指定类型和协议
client = socket.socket()
# 2.通过服务端的地址链接服务端
client.connect(('192.168.1.178',8080))
# 3.直接给服务端发送消息
client.send('我要消费'.encode('utf8'))
# 4.接收服务端发送过来的消息
data = client.recv(1024)
print(data.decode('utf8'))
# 5.断开与服务端的链接
client.close()
代码优化:
1.聊天内容自定义
针对消息采用input获取
2.让聊天循环起来
将聊天的部分用循环包起来
3.用户输入的消息不能为空
本质其实是两边不能都是recv或者send 一定是一方收一方发
4.服务端多次重启可能会报错
Address already in use 主要是mac电脑会报
方式1:改端口号
方式2:博客里面代码拷贝即可
5.当客户端异常断开的情况下 如何让服务端继续服务其他客人
windows服务端会直接报错
mac服务端会有一段时间反复接收空消息延迟报错
异常处理、空消息判断
半连接池的概念
server.listen(5) # 半连接池
当有多个客户端来链接的情况下 我们可以设置等待数量(不考虑并发问题)
假设服务端只有一个人的情况下
在测试半连接池的时候 可以不用input获取消息 直接把消息写死即可
注意:半连接池就是为了缓解服务端和客户端建立链接的压力
问题:
有的同学在重启服务端时可能会遇到
解决问题:
#加入一条socket配置,重用ip和端口
import socket
from socket import SOL_SOCKET,SO_REUSEADDR
sk = socket.socket()
sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字
sk.listen() #监听链接
conn,addr = sk.accept() #接受客户端链接
ret = conn.recv(1024) #接收客户端信息
print(ret) #打印客户端信息
conn.send(b'hi') #向客户端发送信息
conn.close() #关闭客户端套接字
sk.close() #关闭服务器套接字(可选)
错集图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了