socket 的通信过程
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 的通信过程的更多相关文章
- OpenFlow protocol version 1.0 通信过程
参考 李呈:[原创]OpenFlow通信流程解读 OpenFlow protocol version 1.0 通信过程 通信双方: OpenFlow控制器,OpenFlow交换机. 通信模块: Sec ...
- Socket编程之聊天程序 - 模拟Fins/ModBus协议通信过程
设备控制软件编程涉及到的基本通信方式主要有TCP/IP与串口,用到的数据通信协议有Fins与ModBus. 更高级别的通信如.net中的Remoting与WCF在进行C/S架构软件开发时会采用. 本篇 ...
- 【转】wpa_supplicant与wpa_cli之间通信过程
[转]wpa_supplicant与wpa_cli之间通信过程 转自:http://blog.chinaunix.net/uid-26585427-id-4051479.html wpa_suppli ...
- ZLL本地局域网通信过程
Interface_srpcserver -----以灯的状态操作位例 网关与客户端通过Socket API通信,Socket API在socket_server.c中实现,socket_server ...
- SSL、TLS协议格式、HTTPS通信过程、RDP SSL通信过程
相关学习资料 http://www.360doc.com/content/10/0602/08/1466362_30787868.shtml http://www.gxu.edu.cn/college ...
- Dubbo底层采用Socket进行通信详解
由于Dubbo底层采用Socket进行通信,自己对通信理理论也不是很清楚,所以顺便把通信的知识也学习一下. n 通信理论 计算机与外界的信息交换称为通信.基本的通信方法有并行通信和串行通信两种. 1 ...
- Android BLE与终端通信(三)——客户端与服务端通信过程以及实现数据通信
Android BLE与终端通信(三)--客户端与服务端通信过程以及实现数据通信 前面的终究只是小知识点,上不了台面,也只能算是起到一个科普的作用,而同步到实际的开发上去,今天就来延续前两篇实现蓝牙主 ...
- SSL、TLS协议格式、HTTPS通信过程、RDP SSL通信过程(缺heartbeat)
SSL.TLS协议格式.HTTPS通信过程.RDP SSL通信过程 相关学习资料 http://www.360doc.com/content/10/0602/08/1466362_30787868 ...
- SSL及其加密通信过程
SSL及其加密通信过程 什么是SSL SSL英文全称Secure Socket Layer,安全套接层,是一种为网络通信提供安全以及数据完整性的安全协议,它在传输层对网络进行加密.它主要是分为两层: ...
随机推荐
- 【生产环境】Tomcat运行一段时间后访问变慢分析历程
环境运行一天或者几天,网站访问就很卡,手机端app访问页面出现白屏.Tomcat运行一段时间后访问变慢,但是cpu,内存都正常.日志也是发现不了啥.... 问题的原先分析 1.环境配置(cpu,内存, ...
- springboot整合mybatis统一配置bean的别名
mybatis.type-aliases-package=cn.byzt.bean 只需要将 javaBean 的路径配置到 springboot 的配置文件中,这里如果是多个路径,用英文逗号分隔多个 ...
- Solr与Elasticsearch比较
Solr优点1.Solr有一个更大.更成熟的用户.开发和贡献者社区.2.支持添加多种格式的索引,如:HTML.PDF.微软 Office 系列软件格式以及 JSON.XML.CSV 等纯文本格式.3. ...
- 使用厂商MIB库查找设备OID值并实施监控的方法
https://wenku.baidu.com/view/8f4b389e0029bd64783e2cd0.html
- ExpressionTreeVisualizer
看表达式的工具,这个工具后来微软不更新了,只支持到VS2013 表达式树的语法难度太大,语法和实现难度都大 相关文章 github地址
- mysql备份恢复中的常见错误
从A主机备份到B主机 mysqldump -uroot -p vw>vw.sql 现备份数据库文件,需要恢复到目标机B,B的数据库版本为5.5.23,A机器的mysql版本为5.0.2 ...
- Cloud Foundry中DEA与warden通信完毕应用port监听
在Cloud Foundry v2版本号中,DEA为一个用户应用执行的控制模块,而应用的真正执行都是依附于warden. 更详细的来说,是DEA接收到Cloud Controller的请求:DEA发送 ...
- 系统报 “client没有所需的特权” 的解决方法
今在对服务端代码进行单元測试的时候.突然报出例如以下错误: client没有所需的特权 后经网上查找,相同的问题都是属于对C盘读写的问题.回忆自己的项目也须要对C盘进行创建文件夹和读写文件.故尝试运行 ...
- Cocos2d-x3.0RC2 EditBox
EditBox样例 将例如以下代码拷贝到新建的project中就能看到效果. HelloWorldScene.h #include "cocos2d.h" /*这里要引入头文件*/ ...
- WPF带cookie get/post请求网页,下载文件,图片,可保持会话状态
直接写成啦一个MyNet.cs类方便使用 get/post方法请求 //get请求 MyNet.SendRequest("http://www.baidu.com"); //pos ...