Linux网络编程API函数初步剖析

今天我们来分析一下前几篇博文中提到的网络编程中几个核心的API,探究一下当我们调用每个API时,内核中具体做了哪些准备和初始化工作。

1、socket(family,type,protocol)

当我们在开发网络应用程序时,使用该系统调用来创建一个套接字。该API所做的工作如下所示:

该系统调用主要完成两个任务:“创建套接字”和“为套接字绑定文件句柄”。

socket{}<include/linux/net.h>结构定义如下:

struct socket {
socket_state state; //socket状态
unsigned long flags; //标识,如SOCK_ASYNC_NOSAPCE
const struct proto_ops *ops; //协议特定的socket操作集
struct fasync_struct *fasync_list; //异步唤醒队列
struct file *file; //指向文件的指针
struct sock *sk; //指向下一层中的sock结构
wait_queue_head_t wait; //等待在这个socket上的任务列表
short type; //数据包的类型
};

在创建socket套接字时,就是要完成ops、file和sk等这些成员的初始化。

1). 创建套接字:sock_create()

根据family参数值在全局数组struct net_proto_family net_families[]里找到我们所指定的地址簇。不同类型的地址簇都有一个struct net_proto_family{}类型的对象,例如我们常见的IPv4的inet_family_ops,IPv6的inet6_family_ops,X25协议的ax25_family_ops等。在内核是初始化时,这些模块会在自己的初始化函数内部调用sock_register()接口将各自的地址簇对象注册到net_families[]数组里。

我们分析的焦点集中在IPv4协议簇,即inet_family_ops对象上。重点是inet_create函数,该函数的主要任务就是创建一个socket套接字,并对其中相关结构体成员进行必要的初始化。至于它创建套接字时的依据和原理等到我们讲协议栈时大家就明白了,这里主要是让大家对其流程执行流程有个感性的把握。

sock_alloc()函数中我们创建一个struct socket{}类型的对象,假如叫做A,将socket()系统调用的第二参数type字段赋值给A->type。

在inet_create()函数中,我们根据type的值,在全局数组struct inet_protosw inetsw[]里找到我们对应的协议转换开关。而inetsw[]数组是在inet_init()函数里被初始化的:


       其中inetsw_array[]是一个比较重要的数据结构,定义在af_inet.c文件中:

根据type的值,就可以确定struct socket{}->ops,到底是inet_stream_ops、inet_dgram_ops或者inet_sockraw_ops。然后,对应地,就以tcp_prot、udp_prot或raw_prot为输入参数,实例化一个struct sock{}对象sk=sk_alloc()。紧接着建立socket{}和sock{}的关联,最后将socket()系统调用的第三个参数protocol付给sock{}对象中的属性sk_protocol。

看不懂别着急,我说过,这里只是给大家梳理整体流程,等到我们讲了协议栈章节,然后再回头看本篇,就感觉这些东西就太小儿科了。

2). 为套接字绑定文件句柄:sock_map_fd()

我们都知道网络套接字也是一种系统IO,所以不可避免的要与文件系统打交道。每个套接字都对应一个已打开的文件标识符,所以在套接字初始化完成后,就要将其和本地一个唯一的文件标识符关联起来,即建立socket{}和file{}之间的关联关系。

2、bind (sockfd, sockaddr, addrlen)

该系统调用在内核中的执行过程如下:

重点是socket->ops->bind()回调接口。我们现在已经知道了,针对IPv4而言,这里的ops无非就是inet_stream_opsinet_dgram_opsinet_sockraw_ops对象。碰巧的是,这三个对象中的bind函数指针均指向inet_bind()函数。只有原始套接字的情况,这里会去调用raw_prot对象的bind回调函数,即raw_bind()。

3、listen(sockfd, backlog)

这里我们可以看到面向无连接的套接字和原始套接字是不用listen的,只有流式套接字才有效。

4、connect(sockfd, sockaddr, addrlen)

从这幅图中我们确实看到,connect()系统调用不但可以面向连接的套接字,也可用于无连接及原始套接字。

5、accept(sockfd, sockaddr, addrlen)

同样地,我们看到只有面向连接的流式套接字调用accept()才有意义。最终调用的是tcp_prot对象的accept成员函数。

本篇主要进一步分析了网络编程中常见的几个API函数内部的调用流程,一方面可以使大家对这些API的有了更深的认识,不是仅仅停留在形而上的层面;另一方面为后面分析协议栈的实现原理,奠定坚实的基础。

未完,待续…

UNIX网络编程——揭开网络编程常见API的面纱【上】的更多相关文章

  1. UNIX网络编程——揭开网络编程常见API的面纱【下】

    Linux网络编程数据收发的API流程分析        只要把数据在协议栈中的流动线路和脉络弄清楚了,关于协议栈的实现部分,理解起来就轻松多了.在网络编程章节的数据接收过程中,我们主要介绍过read ...

  2. 揭开网络编程常见API的面纱【上】

    Linux网络编程API函数初步剖析 今天我们来分析一下前几篇博文中提到的网络编程中几个核心的API,探究一下当我们调用每个API时,内核中具体做了哪些准备和初始化工作. 1.socket(famil ...

  3. UNIX环境高级编程——TCP/IP网络编程 常用网络信息检索函数

    UNIX环境高级编程——TCP/IP网络编程   常用网络信息检索函数 gethostname()   getppername()   getsockname()   gethostbyname() ...

  4. --系统编程-网络-tcp客户端服务器编程模型、socket、htons、inet_ntop等各API详解、使用telnet测试基本服务器功能

    PART1 基础知识 1. 字节序 网络字节序是大端字节序(低地址存放更高位的字节), 所以,对于字节序为小端的机器需要收发网络数据的场景,要对这些数据进行字节序转换. 字节序转换函数,常用的有四个: ...

  5. Unix环境高级编程(十七)网络IPC套接字

    通过网络套接字可以使得不同计算机上运行的进程相互通信. 1.创建套接字 #include <sys/socket.h> Int socket( int domain, int type, ...

  6. (50)LINUX应用编程和网络编程之五 Linux信号(进程间通信)

                                                                                 信号实现进程间的通信 3.5.1.什么是信号 ...

  7. (46)LINUX应用编程和网络编程之一Linux应用编程框架

    3.1.1.应用编程框架介绍 3.1.1.1.什么是应用编程 (1)整个嵌入式linux核心课程包括5个点,按照学习顺序依次是:裸机.C高级.uboot和系统移植.linux应用编程和网络编程.驱动. ...

  8. 黑马程序员:Java编程_网络编程

    =========== ASP.Net+Android+IOS开发..Net培训.期待与您交流!=========== 网络编程就是两个(或多个)设备(例如计算机)之间的数据传输,更具体的说,网络编程 ...

  9. (47)LINUX应用编程和网络编程之二Linux文件属性

    Linux下的文件系统为树形结构,入口为/ 树形结构下的文件目录: 无论哪个版本的Linux系统,都有这些目录,这些目录应该是标准的.各个Linux发行版本会存在一些小小的差异,但总体来说,还是大体差 ...

随机推荐

  1. [HNOI 2004]树的计数

    Description 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,编程需要 ...

  2. [HNOI 2008]玩具装箱

    Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压 缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1.. ...

  3. [HNOI 2001]产品加工

    Description 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时由两台机 ...

  4. [TJOI 2016&HEOI 2016]排序

    Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...

  5. [UOJ] #217. 【UNR #1】奇怪的线段树

    题解见大佬博客 我的丑陋代码: #include<cstdio> #include<cstring> #include<cstdlib> inline int re ...

  6. [USACO 5.1.3]乐曲主题

    Description 我们用N(1 <= N <=5000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,每个数表示钢琴上的一个键.很不幸这种表示旋律的方法忽略了音符的 ...

  7. AR8033 1000M模式下ping包丢包率过大分析与解决

    1 现象 近期对一款基于QCA方案.有线Phy为AR8033.WiFi双频且支持iEEE802.11AC的WLAN产品进行了深度验证,发现有线口同部分PC机直连时,WiFi终端ping 该PC机时总是 ...

  8. c语言第五次作业0

    ---恢复内容开始--- (一)改错题 输出华氏摄氏温度转换表:输入两个整数lower和upper,输出一张华氏摄氏温度转换表,华氏温度的取值范围是{lower,upper},每次增加2℉.计算公式如 ...

  9. # C语言程序设计第一次作业1234

    ---恢复内容开始--- C语言程序设计第一次作业 1.求圆面积和周长 输入圆的半径,计算圆的周长和面积 (1)流程图 (2)测试数据及运行结果 测试数据r=3 运行结果 2.判断闰年 输入一个四位年 ...

  10. spaCy is a library for advanced natural language processing in Python and Cython:spaCy 工业级自然语言处理工具

    spaCy is a library for advanced natural language processing in Python and Cython. spaCy is built on ...