【Linux学习之网络编程】socket套接字原理总结

什么是socket?

应用层通过传输层传输数据时,TCP或UDP会遇到同时为多个应用进程提供并发的服务, 而多个TCP连接或多个应用程序进程使用同一个TCP协议端口.

为了区别不同的连接和进程,许多计算机操作系统为了应用程序与TCP/IP协议交互提供了称为套接字(socket)的接口,所以,套接字是应用程序和TCP/UDP之间通信的门

Socket描述了一个IP、端口对。它简化了程序员的操作,知道对方的IP以及PORT就可以给对方发送消息,再由服务器端来处理发送的这些消息。所以,Socket一定包含了通信的双发,即客户端(Client)与服务端(server)

socket套接字的通信流程

【Linux学习之网络编程】socket套接字原理总结

流程总结如下:

① 服务器根据地址类型(ipv4,ipv6)、socket类型、协议创建socket(socket()函数)

② 服务器为socket绑定ip地址和端口号(bind()函数)

③ 服务器socket监听端口号请求(listen()函数),准备接收客户端发来的连接,注意,这时候服务器的socket并没有被打开

④ 客户端创建socket, 打开socket,根据服务器ip地址和端口号试图连接服务器socket(connect()函数)

⑤ 服务器socket接收到客户端socket请求,被动打开,开始接收客户端请求,直到客户端返回连接信息(accept()函数),注意,accept函数是阻塞的

⑥ 客户端连接成功,服务器accept方法返回,连接成功

⑦ 客户端和服务器进行send()发送数据和recv()接收数据

⑧ 如果不需要连接了就关闭套接字

socket套接字的工作原理

前面也说了,socket是TCP/IP网络的API接口函数,可以实现不同进程之间的通信(IPC),本机和远程都可以

socket最先应用于Unix操作系统,而在Unix/Linux中有种思想是一切皆文件,所以socket就是种特殊的I/O,有文件描述符,但是只是用于区分,类似的还有进程ID

而实际上一个socket句柄代表两个地址对,"本地IP:port" <--->"远程IP:port",socket是一个内核对象,由操作系统内核为其维护缓冲区,引用计数,并且可以被多个进程使用.

socket()函数创建了一个socket内核对象,accept或者connect之后,才可以会socket句柄进行读写.因为在connect之后或者bind()->listen()->accept()之后才会设置好socket内核对象里面的ip和端口

一. 建立套接字

使用socket建立套接字时,实际上是建立了一个数据结构. 这个数据结构主要的信息是指定了连接的种类使用的协议

调用socket()函数之后,成功的话会返回一个int类型的描述符,指向前面那个被维护在内核里的数据结构. 所以建立了之后,可以像使用文件描述符对文件操作一样, 可以通过向套接字里写数据把数据传送到我们制定的地方

二. 给套接字赋予地址

赋予套接字地址的方式有两种:服务器端使用bind(),客户端使用connect()

1.bind()函数

TCP/IP连接的区分,可以通过一个IP地址和port端口号来区分(如果要区分特定的主机,还需要hostname)

bind函数是用来绑定端口号的,它为一个使用在服务器端的进程中的套接字赋予通信的地址和端口.

通信的IP地址和端口合起来构成了一个socket地址,这个数据结构就是struct sockaddr,bind函数就是把socket套接字和这个数据结构连接起来,就是赋予这个套接字一个地址.

一个socket数据结构和socket地址的数据结构(socket地址就是ip和port),没有bind()之前它们是没有关系的

bind的IP一般是本地IP,所以它最主要的作用就是绑定端口,指定本机的一个端口,为进程和客户端进程之间连接提供通道

2.connect()函数

对于客户端来说,bind()没什么意义,并不是不能使用,所以客户端是通过connect函数建立socket和socket地址,其中的socket地址是它想要连接服务器的socket地址,在connect建立socket和socket地址时,它也在尝试着和远端的连接

三. 建立连接

建立连接上面的流程已经说了

参考博客:

https://blog.csdn.net/hearthougan/article/details/51275765