socket 模块
什么是socket 翻译为套接字
是一套编程接口,内部封装了一堆底层协议,隐藏了内部复杂的实现细节,提供简单的使用接口
咱们只要按照socket编程接口来编写出的代码,就已经遵循了各种协议了
简单的说就是一个封装好的模块
要学习的就是模块的使用方法
socket的发展
最开始socket使用来完成进程间通讯的,并不是用来网络通讯,那时候还没有网络
后来有了网络,基于之前那的socket来进行了更新,使其可以支持网络通讯
所以socket分为两种:
1. AF_UNIX : 进程间通讯
2. AF_INET : 网络通讯
socket在OSI中的位置
使用socket编写服务端:
import socket # 买电话 # 作为服务器必须明确自己的ip和端口号,并且不应该变化 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 默认的就是网络类型与TCP协议 # phone = socket.socket() # 绑定电话卡 # 192.168.13.29 是回送地址, 也就是当前电脑的IP 表示电脑本身 # IP 一定是本机IP, 不过本机可能有多个IP,这里填的是IPv4 的地址 # 注意的是,参数传入的是一个元祖类型,IP地址与端口号放在一个元祖中 phone.bind(('192.168.13.29',8080)) # 无论是服务器,还是客户端,都是socket类型 # 监听 等待端口有无数据传送过来 phone.listen(5) while True: # 接电话 # 建立连接之后,客户端的套接字对象,与客户端的端口 client,address = phone.accept() # 三次握手
# 接受连接请求 # client表示客户端的socket # addr 表示客户端的地址信息 # accept 是一个阻塞函数,会一直等到有客户链接过来,再继续执行
while True: # 接收数据 try:
# 收发消息
# 发送数据与接收数据,对方可能会异常下线,都放入try中
msg = client.recv(1024)
# 在linux,windows中,对方如果强行下线了,服务器不会抛出异常,只会收到空消息 # 故需要嘉盛if判断,如果为空,则意味着对方下线了,应该关闭链接,跳出循环
if not msg: client.send('你有病'.encode('utf-8')) print(msg.decode('utf-8')) # 发送数据 client.send(msg+'sb'.encode('utf-8')) except: print('客户端已断开') client.close() break # 通常服务器不会关闭
使用socket编写客户端:
import socket # 买电话 # 参数1指定socket 类型AF_INET 表示网络类型 # 参数2 指定的传输协议为 SOCK_STREAM表示TCP协议 SOCK_DGRAM表示为UDP协议 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 连接服务器 # 作为客户端,IP 和端口可以变化,所有系统会自动分配随机端给客户端 phone.connect(('192.168.13.29',8080)) while True: try: # 发送数据 cmd = input('请输入指令') if not cmd:continue if cmd == 'q':break phone.send(cmd.encode('utf-8')) # 接收数据 msg = phone.recv(1024) print(msg.decode('utf-8')) except: print('服务器已关闭') break # 关闭访问(挂电话) phone.close()
基于socket套接字编程异常
1. 客户端或服务端因异常断线
2. 端口占用问题
如果已经开启了服务器 再次运行将会抛出 端口占用异常 把之前开启的服务器关掉即可
有些情况 明明已经关闭了进程 但是 还是端口占用
可能是进程正在后台运行 可以通过端口查出进程 进行关闭
windows下
netstat -ano | findstr 9898
tasklist | findstr 进程id 拿到进程名称
taskkill /f /t /im 进程名称
大招: 重启电脑