1. C/S 架构
C/S 架构即客户端/服务端架构,B/S 架构(浏览器与服务端)也是 C/S 架构的一种。
C/S 架构与 socket 的关系:学习 socket 可以完成 C/S 架构的开发。
2. osi 七层
一个完整的计算机系统由硬件、操作系统以及应用软件三部分组成,但是不能与其他计算机通信,这时就需要用到互联网。
互联网的核心是由一堆协议组成,协议就是标准。所有的计算机按照统一的标准去收发信息从而完成通信。
按照分工不同,将互联网协议从逻辑上划分为七层:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
3. socket 层
C/S架构软件属于应用层,是基于网络进行通讯的。网络的核心是协议,那么要想开发一款应用软件,就需要遵循 TCP/UDP协议。
然而 TCP/UDP 知识何其多,需要花费大量的时间去学习,大大减小了开发效率。
问题:那到底什么是 socket 呢?
socket 是应用层与传输层(TCP/UDP协议)通讯的中间软件抽象层。它封装了 TCP/UDP协议,并提供一组接口,供开发软件使用。
开发一款软件只需调用接口,就能遵循 TCP/UDP协议,我们无需再深入理解 TCP/UDP协议。
也人说 socket 是 ip + port,ip 用来标识一台主机位置,配置在网卡上。而 port 用来标识计算机上的一个程序,由应用程序开启,两者结合标识了独一无二的一个应用程序。
程序的 pid 是应用程序进程或线程的标识,一个程序往往有多个 pid。
4. 套接字发展历史及分类
socket 又称为套接字,起源于 20世纪70年代加利福利亚伯克利分校版本的 Unix,即 BSD Unix。又称为 伯克利套接字或 BSD 套接字。
刚开始套接字被设计为在同一主机上多个应用程序之间的通讯,也被称为进程间通讯或 IPC
分类
- 基于文件类型的套接字家族
- **家族名字:**AF_UNIX
- unix 一切皆文件,基于文件的套接字就是调用底层的文件系统来获取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信。
- 基于网络类型的套接字家族
- **家族名字:**AF_INET
5. 套接字工作流程
服务器端:
先初始化 socket,然后与端口绑定(bind),对端口进行监听(listen),调用 accept 阻塞,等待客户连接。
客户端:
初始化一个 socket,然后连接服务器(connect),如果连接成功,那么客户端与服务端连接的连接就建立好了。
客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。
服务端:
import socket
ip_port = ('127.0.0.1', 8000)
back_log = 5
buffer_size = 1024
# socket.AF_INET:基于网络 socket.SOCK_STREAM:tcp 协议
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(ip_port) # 手机插卡,如果元组为('',9000)表示本机所有的网卡,相当于0.0.0.0
s.listen(back_log) # 手机开机,5 表示用于 tcp 连接的优化
conn, addr = s.accept() # 等电话
print('来自%s的电话' % addr[0])
msg = conn.recv(buffer_size) # 收消息
print('客户端发来信息:', msg)
conn.send(msg.upper()) # 发消息
conn.close() # 挂电话
s.close() # 关机
来自127.0.0.1的电话
客户端发来信息: b'hello'
客户端:
import socket
ip_port = ('127.0.0.1', 8000)
buffer_size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 买手机
s.connect(ip_port) # 拨电话
s.send('hello'.encode('utf-8')) # 发消息
feedback = s.recv(buffer_size) # 收信息
print('接收到服务端的信息%s' % feedback.decode('utf-8'))
s.close() # 挂电话
接收到服务端的信息HELLO