1.建立套接字

Linux在利用socket()系统调用建立新的套接字时,需要传递套接字的地址族标识符、套接字类型以及协议,其函数定义于net/socket.c中:

asmlinkage long sys_socket(int family, int type, int protocol)

{

int retval;

struct socket *sock;

retval = sock_create(family, type, protocol, &sock);

if (retval < 0)

goto out;

retval = sock_map_fd(sock);

if (retval < 0)

goto out_release;

out:

/* It may be already another descriptor 8) Not kernel problem. */

return retval;

out_release:

sock_release(sock);

return retval;

}

实际上,套接字对于用户程序而言就是特殊的已打开的文件。内核中为套接字定义了一种特殊的文件类型,形成一种特殊的文件系统sockfs,其定义于net/socket.c:

static struct vfsmount *sock_mnt;

static DECLARE_FSTYPE(sock_fs_type, "sockfs", sockfs_read_super, FS_NOMOUNT);

在系统初始化时,要通过kern_mount()安装这个文件系统。安装时有个作为连接件的vfsmount数据结构,这个结构的地址就保存在一个全局的指针sock_mnt中。所谓创建一个套接字,就是在sockfs文件系统中创建一个特殊文件,或者说一个节点,并建立起为实现套接字功能所需的一整套数据结构。所以,函数sock_create()首先是建立一个socket数据结构,然后将其“映射”到一个已打开的文件中,进行socket结构和sock结构的分配和初始化。

新创建的 BSD socket 数据结构包含有指向地址族专有的套接字例程的指针,这一指针实际就是 proto_ops 数据结构的地址。

BSD 套接字的套接字类型设置为所请求的 SOCK_STREAM 或 SOCK_DGRAM 等。然后,内核利用 proto_ops 数据结构中的信息调用地址族专有的创建例程。

之后,内核从当前进程的 fd 向量中分配空闲的文件描述符,该描述符指向的 file 数据结构被初始化。初始化过程包括将文件操作集指针指向由 BSD 套接字接口支持的 BSD 文件操作集。所有随后的套接字(文件)操作都将定向到该套接字接口,而套接字接口则会进一步调用地址族的操作例程,从而将操作传递到底层地址族
实际上,socket结构与sock结构是同一事物的两个方面。如果说socket结构是面向进程和系统调用界面的,那么sock结构就是面向底层驱动程序的。可是,为什么不把这两个数据结构合并成一个呢?

我们说套接字是一种特殊的文件系统,因此,inode结构内部的union的一个成分就用作socket结构,其定义如下:

struct inode {

union {

struct socket             socket_i;

}

}

由于套接字操作的特殊性,这个结构中需要大量的结构成分。可是,如果把这些结构成分全都放在socket结构中,则inode结构中的这个union就会变得很大,从而inode结构也会变得很大,而对于其他文件系统,这个union成分并不需要那么庞大。因此,就把套接字所需的这些结构成分拆成两部分,把与文件系统关系比较密切的那一部分放在socket结构中,把与通信关系比较密切的那一部分则单独组成一个数据结构,即sock结构。由于这两部分数据在逻辑上本来就是一体的,所以要通过指针互相指向对方,形成一对一的关系。

2.在 INET BSD 套接字上绑定(bind)地址

为了监听传入的 Internet 连接请求,每个服务器都需要建立一个 INET BSD 套接字,并且将自己的地址绑定到该套接字。绑定操作主要在 INET 套接字层中进行,还需要底层 TCP 层和 IP 层的某些支持。将地址绑定到某个套接字上之后,该套接字就不能用来进行任何其他的通讯,因此,该 socket数据结构的状态必须为 TCP_CLOSE。传递到绑定操作的 sockaddr 数据结构中包含要绑定的 IP地址,以及一个可选的端口地址。通常而言,要绑定的地址应该是赋予某个网络设备的 IP 地址,而该网络设备应该支持 INET 地址族,并且该设备是可用的。利用 ifconfig 命令可查看当前活动的网络接口。被绑定的 IP 地址保存在 sock 数据结构的rcv_saddr 和 saddr 域中,这两个域分别用于哈希查找和发送用的 IP 地址。端口地址是可选的,如果没有指定,底层的支持网络会选择一个空闲的端口。

当底层网络设备接受到数据包时,它必须将数据包传递到正确的 INET 和 BSD 套接字以便进行处理,因此,TCP维护多个哈希表,用来查找传入 IP 消息的地址,并将它们定向到正确的socket/sock 对。TCP 并不在绑定过程中将绑定的 sock 数据结构添加到哈希表中,在这一过程中,它仅仅判断所请求的端口号当前是否正在使用。在监听操作中,该 sock 结构才被添加到 TCP 的哈希表中。

3.在 INET BSD 套接字上建立连接(connect)

创建一个套接字之后,该套接字不仅可以用于监听入站的连接请求,也可以用于建立出站的连接请求。不论怎样都涉及到一个重要的过程:建立两个应用程序之间的虚拟电路。出站连接只能建立在处于正确状态的 INET BSD 套接字上,因此,不能建立于已建立连接的套接字,也不能建立于用于监听入站连接的套接字。也就是说,该 BSD socket 数据结构的状态必须为 SS_UNCONNECTED。

在建立连接过程中,双方 TCP 要进行三次“握手”,具体过程在 本章第二节——网络协议一文中有详细介绍。如果 TCP sock 正在等待传入消息,则该 sock 结构添加到 tcp_listening_hash 表中,这样,传入的 TCP 消息就可以定向到该 sock 数据结构。

4.监听(listen) INET BSD 套接字

当某个套接字被绑定了地址之后,该套接字就可以用来监听专属于该绑定地址的传入连接。网络应用程序也可以在未绑定地址之前监听套接字,这时,INET 套接字层将利用空闲的端口编号并自动绑定到该套接字。套接字的监听函数将 socket 的状态改变为 TCP_LISTEN。

当接收到某个传入的 TCP 连接请求时,TCP 建立一个新的 sock 数据结构来描述该连接。当该连接最终被接受时,新的 sock 数据结构将变成该 TCP 连接的内核bottom_half部分,这时,它要克隆包含连接请求的传入 sk_buff 中的信息,并在监听 sock 数据结构的 receive_queue 队列中将克隆的信息排队。克隆的 sk_buff 中包含有指向新 sock 数据结构的指针。

5.接受连接请求 (accept)

接受操作在监听套接字上进行,从监听 socket 中克隆一个新的 socket 数据结构。其过程如下:接受操作首先传递到支持协议层,即 INET 中,以便接受任何传入的连接请求。相反,接受操作进一步传递到实际的协议,例如 TCP 上。接受操作可以是阻塞的,也可以是非阻塞的。接受操作为非阻塞的情况下,如果没有可接受的传入连接,则接受操作将失败,而新建立的 socket 数据结构被抛弃。接受操作为阻塞的情况下,执行阻塞操作的网络应用程序将添加到等待队列中,并保持挂起直到接收到一个 TCP 连接请求为至。当连接请求到达之后,包含连接请求的 sk_buff 被丢弃,而由 TCP 建立的新 sock 数据结构返回到 INET 套接字层,在这里,sock 数据结构和先前建立的新 socket 数据结构建立链接。而新 socket 的文件描述符(fd)被返回到网络应用程序,此后,应用程序就可以利用该文件描述符在新建立的 INET BSD 套接字上进行套接字操作。

https://www.cnblogs.com/SophiaTang/archive/2012/02/05/2339365.html

socket 的通信过程的更多相关文章

  1. OpenFlow protocol version 1.0 通信过程

    参考 李呈:[原创]OpenFlow通信流程解读 OpenFlow protocol version 1.0 通信过程 通信双方: OpenFlow控制器,OpenFlow交换机. 通信模块: Sec ...

  2. Socket编程之聊天程序 - 模拟Fins/ModBus协议通信过程

    设备控制软件编程涉及到的基本通信方式主要有TCP/IP与串口,用到的数据通信协议有Fins与ModBus. 更高级别的通信如.net中的Remoting与WCF在进行C/S架构软件开发时会采用. 本篇 ...

  3. 【转】wpa_supplicant与wpa_cli之间通信过程

    [转]wpa_supplicant与wpa_cli之间通信过程 转自:http://blog.chinaunix.net/uid-26585427-id-4051479.html wpa_suppli ...

  4. ZLL本地局域网通信过程

    Interface_srpcserver -----以灯的状态操作位例 网关与客户端通过Socket API通信,Socket API在socket_server.c中实现,socket_server ...

  5. SSL、TLS协议格式、HTTPS通信过程、RDP SSL通信过程

    相关学习资料 http://www.360doc.com/content/10/0602/08/1466362_30787868.shtml http://www.gxu.edu.cn/college ...

  6. Dubbo底层采用Socket进行通信详解

    由于Dubbo底层采用Socket进行通信,自己对通信理理论也不是很清楚,所以顺便把通信的知识也学习一下. n  通信理论 计算机与外界的信息交换称为通信.基本的通信方法有并行通信和串行通信两种. 1 ...

  7. Android BLE与终端通信(三)——客户端与服务端通信过程以及实现数据通信

    Android BLE与终端通信(三)--客户端与服务端通信过程以及实现数据通信 前面的终究只是小知识点,上不了台面,也只能算是起到一个科普的作用,而同步到实际的开发上去,今天就来延续前两篇实现蓝牙主 ...

  8. SSL、TLS协议格式、HTTPS通信过程、RDP SSL通信过程(缺heartbeat)

    SSL.TLS协议格式.HTTPS通信过程.RDP SSL通信过程   相关学习资料 http://www.360doc.com/content/10/0602/08/1466362_30787868 ...

  9. SSL及其加密通信过程

    SSL及其加密通信过程 什么是SSL SSL英文全称Secure Socket Layer,安全套接层,是一种为网络通信提供安全以及数据完整性的安全协议,它在传输层对网络进行加密.它主要是分为两层: ...

随机推荐

  1. 洛谷P1316 丢瓶盖【二分+递推】

    陶陶是个贪玩的孩子,他在地上丢了A个瓶盖,为了简化问题,我们可以当作这A个瓶盖丢在一条直线上,现在他想从这些瓶盖里找出B个,使得距离最近的2个距离最大,他想知道,最大可以到多少呢? 输入输出格式 输入 ...

  2. [POI2005]BAN-Bank Notes

    [POI2005]BAN-Bank Notes POI真好玩.. 如果没有记录方案的话就是一个简单的二进制或单调队列优化多重背包的问题. 但是非常难受的是要记录方案. 而且空间只给了\(64MB\), ...

  3. python-if判断

    1. python 条件语句 Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. 可以通过下图来简单了解条件语句的执行过程: Python程序语言指定任何 ...

  4. Spring深入理解(一)

    Spring 框架的设计理念与设计模式分析 Spring核心组件 Spring 框架中的核心组件只有三个:Core.Context 和 Beans Spring 的设计理念 前面介绍了 Spring ...

  5. POJ 2607

    一次FLOYD,再枚举. 注意题目要求的输出是什么哦. #include <iostream> #include <cstdio> #include <cstring&g ...

  6. [React Native] Reduce Long Import Statements in React Native with Absolute Imports

    In large React Native projects, it’s common to have long relative import paths like: import MyCompon ...

  7. IOS - 查找未使用的图片

    实现细节都在代码里面, 帮助 -h. # -*- coding: utf-8 -*- """ 检查IOS应用图片是否使用 1. 读取有效文件: 图片(.png, .jpg ...

  8. Netty In Action中文版 - 第十五章:选择正确的线程模型

    http://blog.csdn.net/abc_key/article/details/38419469 本章介绍 线程模型(thread-model) 事件循环(EventLoop) 并发(Con ...

  9. Java类的多态机制

    Java中将一个方法调用同一个方法主体关联起来被称作绑定. 绑定分为前期绑定和后期绑定.前期绑定是在编译器决定的,而后期绑定是在程序运行时决定的.Java中除了static方法和final方法(pri ...

  10. CentOS 7通过yum安装fcitx五笔输入法

    CentOS 7通过yum安装fcitx五笔输入法 下面通过了亲測: 1.设置源 Posted in Linux at 三月 5th, 2015 / No Comments ? 增加EPEL源 EPE ...