计算机网络学习随笔记(Socket协议)

    技术2023-11-10  78

    Socket

    基于 TCP 协议的 Socket 程序函数调用过程

    在两端创建了Socket之后,TCP的服务需要先监听一个端口,一般是调用bind函数,给这个Socket赋予一个IP地址和端口。端口是用来标识对应的应用程序的,IP地址是标识对应的机器。

    当服务器有了IP和端口后,就可以调用listen函数进行监听。在TCP的状态图中,有一个listen状态,在调用这个函数之后,服务端就进入了这个状态,客户端就可以建立连接了。

    在内核中,为每个Socket维护两个队列。一个是已经建立了连接的队列(三次握手已经完成)处于established 状态;还有一个是未建立连接的队列(三次握手未完成)处于 syn_rcvd 的状态;

    接下来,服务端调用accept函数,拿出一个已经完成的连接进行处理,如果没有完成就等待。在服务端等待的时候,客户端可以通过connect函数发起连接。首先在参数中指定要连接的IP地址和端口号,然后发起三次握手,内核会给客户端分配一个临时的端口。一旦握手成功,服务端的accept就会返回另一个Socket。

    连接建立成功后,双方开始通过read和write函数来读写数据,就像往一个文件流当中写数据,具体步骤如下图所示:

    Socket在Linux中就是以文件的形式存在的,包含了文件描述符。写入写出,也是通过文件描述符。每一个进程都是有一个数据结构task_struct,里面指向一个文件描述符数组,包含了这个进程打开的所有文件的文件描述符。文件描述符是一个整数,是这个数组的下标。这个数组中的内容是一个指针,指向内核中所有打开的文件的列表。每个文件都会有一个inode,而Socket对应的inode不像真正的文件系统保存在磁盘上,而是存在内存当中的。这个inode指向了Socket在内核中的Socket结构。在这个结构里面有两个队列,一个队列为发送队列,一个是接收队列。在这两个队列里面保存的是一个缓存sk_buff。整个数据结构图如下:

    基于 UDP 协议的 Socket 程序函数调用过程

    对于UDP来说,UDP不需要连接,不需要经过三次握手。就不需要调用listen和connect,但是UDP的交互还是需要端口号跟IP地址的,所有需要bind。因为UDP是没有建立连接的所有只需要一个Socket就行了不需要一组Socket。每次通信的时候,都调用sendto和recvfrom,都可以传入端口号和IP地址。 下图为调用过程:

     

     

    Processed: 0.008, SQL: 9