socket套接字:
Socket是应用层与TCPIP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
也有人说socket就是以IP+port的一种组合,通过两者结合完成了定位世界上唯一一台主机的应用程序的定位。
套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。
套接字中基于文件类型的家族:
AF_UNIX:两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
套接字中基于网络的家族:
AF_INET:运行在两台机器的进程,根据互联网协议来进行通信
套接字工作流程:
根据TCP协议的传输我们有两个目标,客户端和服务端
我们先来看客户端,首先我们假设已经得到了数据,所以先调用socket套接字对象,得到对象之后我们需要调用传输层,先建立TCP连接connect()接口,通过调用接口后我们得到一个对象,通过调用对象下的方法发送数据和接受数据。
最后在关闭该链接。
同时我们再来看服务端,首先也是要根据协议来调用socket接口,然后要使用bind绑定一个端口号,这样我们就获得了一个固定的且唯一的位置,接下来定义半链接池的大小,之后从半链接池中取出链接请求完成链接,通过调用接口后我们得到一个对象,通过调用对象下的方法发送数据和接受数据。
最后在关闭该链接。
我们为什么需要固定服务端位置而不是客户端呢?
我们可以进行一个思考,如果我们访问的网站每天位置都在变化,用户体验是如何的呢?由此我们得出结论服务端的位置要固定,那客户端呢,我们的ip是自动获取的同时考虑到高并发的情况客户端不能同时也不应该写死。
import socket # 1、买手机 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp协议 # 2、绑定手机卡 phone.bind(('127.0.0.1',8083)) # 0-65535, 1024以前的都被系统保留使用 # 3、开机 phone.listen(5) # 5指的是半连接池的大小 print('服务端启动完成,监听地址为:%s:%s' %('127.0.0.1',8080)) # 4、等待电话连接请求:拿到电话连接conn conn,client_addr=phone.accept() # 5、通信:收发消息 while True: try: data=conn.recv(1024) # 最大接收的数据量为1024Bytes,收到的是bytes类型 if len(data) == 0: # 在unix系统洗,一旦data收到的是空 # 意味着是一种异常的行为:客户度非法断开了链接 break print("客户端发来的消息:",data.decode('utf-8')) conn.send(data.upper()) except Exception: # 针对windows系统 break # 6、关闭电话连接conn(必选的回收资源的操作) conn.close() # 7、关机(可选操作) phone.close() import socket #1、买手机 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 流式协议=》tcp协议 #2、拨通服务端电话 phone.connect(('127.0.0.1',8083)) #3、通信 while True: msg=input("输入要发送的消息>>>: ").strip() #msg='' if len(msg) == 0:continue phone.send(msg.encode('utf-8')) print('======?') data=phone.recv(1024) print(data.decode('utf-8')) #4、关闭连接(必选的回收资源的操作) phone.close()