Bootstrap

Socket 编程原理

socket编程

基本概念

socket编程即计算机网络编程,目的是使两台主机能够进行远程连接,既然要使两者产生联系,那么就要有至少一个信息发送端和一个信息接收端,因此形成了现在绝大多数 socket 编程都会用到的 C/S 架构(Client[客户端]/Server[服务端]),最典型的应用就是 web服务器/客户端。
在 Unix/Linux 中执行任何形式的 I/O 操作(比如网络连接)时,都是在读取或写入一个文件描述符,而在 Windows 中则被称为文件句柄,其本质都是一个东西,但是 Windows系统会把 socket 当成一个网络连接,需要调用专门设计的数据传输函数。
socket (套接字)是一种抽象层,程序通过它来收发数据,就像打开一个句柄将数据写在存储器上一样,使用 socket 能将程序放在网络中,并与同一网络下其他计算机进行通信。
现在问题又来了,主机内部应用间进行通信,不同应用可用进程号作为唯一标识,那么在网络间通信用什么作为唯一标识呢?其实 TCP/IP 协议簇已经解决了问题,在网络层 IP 地址可以用作网络中主机的唯一标识,传输层的"协议+端口"可用作主机应用的唯一标识,因此利用三元组(IP地址、协议、端口)就可以标识网络应用了,网络应用间可以用三元组作为标志和其他应用进行交互,socket 通信大致如下:
在这里插入图片描述
如图所示,应用程序进程在网络间的通信全部通过 socket 与底层协议交互,进行网络通信,但是 socket 并没有层的概念,它只是一种设计模式(软件抽象层),方便编程而已。

编程流程

socket 编程的底层实现是基于 TCP 和 UDP 的,因此其编程的流程也是围绕着这两个协议的客户端、服务端来进行的,大致流程如下图:
在这里插入图片描述

socket函数

在实现上述功能的过程中,要用到很多接口函数,这一节就针对这些接口函数作详细解释。
1、socket()
这个函数作用是创建一个 socket 的操作对象,它被用作 socket 描述符的唯一标识(相当于文件描述符),在本地我们可以用这个对象进行文件操作,在主机远程连接时则可以用于建立连接、收发数据。
2、bind()
这是服务器端特有的接口函数,把 socket 对象和服务器的 IP 地址、开放端口绑定在一起,在 listen() 的调用下提供服务,客户端可以通过这个来连接服务器。但是客户端是没有 bind() 绑定地址和端口的,因为客户端不用发起监听,在客户端是在调用 connect() 时由系统随机生成一个。
3、listen()
也是服务器端特有的一个接口函数,作用是监听一个端口是否有数据发送过来,函数工作的时候会调用 bind() 函数,获取里面的套接字、地址和端口信息,如果有指向这个套接字描述符、本服务器地址和正在监听的这个端口的连接发送过来,则会让其通过并开始建立连接。
4、connect()
这个函数接口是 TCP 客户端特有的,用于向服务器发起连接建立请求。只要在 connect() 的参数中输入目标服务器的地址和端口,就会向目标发起连接请求,在服务端收到请求后就会调用 accept() 开始自动进行三次握手,从而建立连接。
5、accept()
这个函数接口是 TCP 服务端特有的,当 listen() 监听到请求后就会调用这个函数去建立连接,也就是说,只要这个函数执行成功,与客户端的连接就建立完成,并且可以互相传输数据了。
6、recv(),recvfrom()
这两个函数接口是用来接收数据的,recv() 方法对应 TCP 数据流,recvfrom() 则对应 UDP 数据流,因为 TCP 面向连接而 UDP 传输数据并不创建连接,所以要分这两种办法进行数据的接收。
7、send(),sendto()
和第 6 点的函数接口类似,但是用于发送数据的,和 recv()、recvfrom() 一起实现了网络中不同进程间的通信,其中 send() 对应 TCP 的传输方式,sendto() 对应的是 UDP 的传输方式。
8、read(),

;