操作系统实战 45 讲
彭东
网名 LMOS,Intel 傲腾项目关键开发者
65203 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 60 讲
尝尝鲜:从一个Hello到另一个Hello (2讲)
特别放送 (1讲)
操作系统实战 45 讲
15
15
1.0x
00:00/00:00
登录|注册

40 | 瞧一瞧Linux:详解socket的接口实现

shutdown函数
sys_recv函数
recv函数
sys_send函数
send函数
accept函数
sys_listen函数
sys_connect函数
inet_bind函数
sys_bind函数
协议族的套接字创建函数
sock_alloc函数
sock_create函数
socket函数调用流程
Linux使用内核套接字概念与用户空间套接字通信
传输层以上的功能在用户地址空间完成
Linux内核实现的套接字接口
TCP三次握手发生在socket的哪几个函数中
关闭连接
接收数据
发送数据
被动接收连接
监听套接字
主动连接
套接字的绑定
套接字的创建
套接字接口
思考题
瞧一瞧Linux:详解socket的接口实现

该思维导图由 AI 生成,仅供参考

你好,我是 LMOS。
上节课,我们一起了解了套接字的工作机制和数据结构,但套接字有哪些基本接口实现呢?相信学完这节课,你就能够解决这个问题了。
今天我会和你探讨套接字从创建、协议接口注册与初始化过程,还会为你深入分析套接字系统,是怎样调用各个功能函数的。通过这节课,相信你可以学会基于套接字来编写网络应用程序。有了之前的基础,想理解这节课并不难,让我们正式开始吧。

套接字接口

套接字接口最初是 BSD 操作系统的一部分,在应用层与 TCP/IP 协议栈之间接供了一套标准的独立于协议的接口。
Linux 内核实现的套接字接口,将 UNIX 的“一切都是文件操作”的概念应用在了网络连接访问上,让应用程序可以用常规文件操作 API 访问网络连接。
从 TCP/IP 协议栈的角度来看,传输层以上的都是应用程序的一部分,Linux 与传统的 UNIX 类似,TCP/IP 协议栈驻留在内核中,与内核的其他组件共享内存。传输层以上执行的网络功能,都是在用户地址空间完成的。
Linux 使用内核套接字概念与用户空间套接字通信,这样可以让实现和操作变得更简单。Linux 提供了一套 API 和套接字数据结构,这些服务向下与内核接口,向上与用户空间接口,应用程序正是使用这一套 API 访问内核中的网络功能。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了Linux套接字接口的实现过程,从套接字的创建、绑定到主动连接等方面进行了详细介绍。Linux内核实现的套接字接口将UNIX的“一切都是文件操作”的概念应用在了网络连接访问上,让应用程序可以用常规文件操作API访问网络连接。文章详细解释了套接字的创建过程,包括通用套接字创建的初始化功能和特定协议族的套接字创建函数的调用流程。此外,还介绍了套接字的绑定操作和主动连接的过程。通过深入的技术分析,为读者提供了对Linux套接字接口实现的全面了解,适合对网络编程感兴趣的读者阅读学习。 文章还介绍了监听套接字、被动接收连接、发送数据和接收数据的具体实现过程,以及关闭连接的操作。通过对sys_listen、sys_accept4_file、sys_send和sys_recv等函数的分析,读者可以了解套接字在Linux内核中的实现细节。此外,文章还提到了套接字编程的六个步骤,包括创建套接字、绑定地址、建立连接、监听套接字、发送和接收数据以及关闭释放套接字。 总之,本文通过深入的技术分析,为读者提供了对Linux套接字接口实现的全面了解,适合对网络编程感兴趣的读者阅读学习。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《操作系统实战 45 讲》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(9)

  • 最新
  • 精选
  • neohope
    置顶
    四次挥手过程分析下【V5.8,正常流程】 5、客户端收到FIN包,子状态从TCP_FIN_WAIT2变为TCP_TIME_WAIT,返回ACK包 A、状态和子状态都为TCP_TIME_WAIT 【tcp_protocol.handler】tcp_v4_rcv-> ->if (sk->sk_state == TCP_TIME_WAIT) goto do_time_wait; ->do_time_wait: ->tcp_timewait_state_process ->->if (tw->tw_substate == TCP_FIN_WAIT2) ->->tw->tw_substate = TCP_TIME_WAIT; ->->inet_twsk_reschedule,重新设置回调时间 ->->return TCP_TW_ACK; B、返回ACK ->case TCP_TW_ACK: ->tcp_v4_timewait_ack(sk, skb); 6、服务端收到ACK包,状态从TCP_LAST_ACK变为TCP_CLOSE 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_state_process ->case TCP_LAST_ACK: ->tcp_done ->->tcp_set_state(sk, TCP_CLOSE); 7、客户端超时回调 A、超时时间定义 #define TCP_TIMEWAIT_LEN (60*HZ) #define TCP_FIN_TIMEOUT TCP_TIMEWAIT_LEN B、超时后,回调tw_timer_handler->inet_twsk_kill,进行inet_timewait_sock清理工作 C、没有找到状态变从TCP_TIME_WAIT变为TCP_CLOSE的代码 D、只看没调,有问题的,欢迎小伙伴告诉一下

    作者回复: 66666

    2021-08-15
    4
  • neohope
    置顶
    四次挥手过程分析上【V5.8,正常流程】 1、客户端主动断开连接,状态从TCP_ESTABLISHED变为TCP_FIN_WAIT1,发送FIN包给服务端 A、状态变为TCP_FIN_WAIT1 tcp_close->tcp_close_state ->tcp_set_state(sk, new_state[TCP_ESTABLISHED]),也就是TCP_FIN_WAIT1 B、发送FIN包 tcp_close->tcp_close_state ->tcp_send_fin 2、服务端收到FIN包,状态从TCP_ESTABLISHED变为TCP_CLOSE_WAIT,并返回ACK包 A、状态变为TCP_CLOSE_WAIT 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_established ->tcp_data_queue ->->tcp_fin ->->->inet_csk_schedule_ack; 安排ack ->->->sk->sk_shutdown |= RCV_SHUTDOWN; 模拟了close ->->->sock_set_flag(sk, SOCK_DONE); ->->->case TCP_ESTABLISHED: ->->->tcp_set_state(sk, TCP_CLOSE_WAIT); 修改状态 ->->inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW; ACS是否立即发送 B、发送ACK包 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_established【接上面】 ->tcp_ack_snd_check->__tcp_ack_snd_check->tcp_send_ack 3、客户端收到ACK包,状态从TCP_FIN_WAIT1变为TCP_FIN_WAIT2,然后被替换为状态TCP_TIME_WAIT,子状态TCP_FIN_WAIT2 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_state_process ->case TCP_FIN_WAIT1: ->tcp_set_state(sk, TCP_FIN_WAIT2); ->tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); ->->tw = inet_twsk_alloc(sk, tcp_death_row, state); ->->->tw->tw_state = TCP_TIME_WAIT; ->->->tw->tw_substate = TCP_FIN_WAIT2; ->->->timer_setup(&tw->tw_timer, tw_timer_handler, TIMER_PINNED); 4、服务端状态从TCP_CLOSE_WAIT变为TCP_LAST_ACK,发送FIN包 A、状态变为TCP_LAST_ACK tcp_close->tcp_close_state ->tcp_set_state(sk, new_state[TCP_CLOSE_WAIT]),也就是TCP_LAST_ACK B、发送FIN包 tcp_close->tcp_close_state ->tcp_send_fin
    2021-08-15
    2
  • neohope
    置顶
    三次握手过程分析【V5.8,正常流程】 1、客户端发起第一次握手,状态调变为TCP_SYN_SENT,发送SYN包 connect->__sys_connect->__sys_connect_file->【sock->ops->connect】tcp_v4_connect A、状态变化 ->tcp_set_state(sk, TCP_SYN_SENT); B、发送SYN ->tcp_connect->tcp_send_syn_data 2、服务端收到客户端的SYN包,初始化socket,状态从TCP_LISTEN变为TCP_NEW_SYN_RECV,发送第二次握手SYN_ACK包 A、收到连接,初始化socket accept->__sys_accept4->__sys_accept4_file->【sock->ops->accept】inet_csk_accept B、收到SYN,改变状态 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_state_process-> ->case TCP_LISTEN: ->[sock->ops->conn_request]tcp_v4_conn_request->tcp_conn_request ->->inet_reqsk_alloc ->->->ireq->ireq_state = TCP_NEW_SYN_RECV; C、发送SYN_ACK包 ->[sock->ops->conn_request]tcp_v4_conn_request->tcp_conn_request【和B路径一样】 ->->【af_ops->send_synack】tcp_v4_send_synack ->->->tcp_make_synack ->->->__tcp_v4_send_check 3、客户端收到SYN_ACK包,状态从TCP_SYN_SENT变为TCP_ESTABLISHED,并发送ACK包 A、收到SYN_ACK包 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_state_process ->case TCP_SYN_SENT: ->tcp_rcv_synsent_state_process->tcp_finish_connect ->->tcp_set_state(sk, TCP_ESTABLISHED); B、发送ACK包 ->tcp_rcv_synsent_state_process->tcp_send_ack->__tcp_send_ack 4、服务端收到ACK包,状态从TCP_NEW_SYN_RECV变为TCP_SYN_RECV【实际上是新建了一个sock】 【tcp_protocol.handler】tcp_v4_rcv-> ->if (sk->sk_state == TCP_NEW_SYN_RECV) ->tcp_check_req ->->【inet_csk(sk)->icsk_af_ops->syn_recv_sock】tcp_v4_syn_recv_sock->tcp_create_openreq_child->inet_csk_clone_lock ->->->inet_sk_set_state(newsk, TCP_SYN_RECV); 5、服务端状态从TCP_SYN_RECV变为TCP_ESTABLISHED 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_state_process ->case TCP_SYN_RECV: ->tcp_set_state(sk, TCP_ESTABLISHED); 只看没调,有问题的欢迎各位小伙伴指出。

    作者回复: 是的 总结到位

    2021-08-14
    5
  • pedro
    今天的问题不好回答,因为文中无明显三次握手的代码,而且三次握手的机制其实比较复杂,涉及到几个状态和几个队列之间的切换,笼统的 connect 和 accept 函数是说不清楚的,感兴趣可以看看这里: https://blog.csdn.net/tennysonsky/article/details/45621341 当然这些不能全信,所以还是得自己看linux内核代码,待我看了再来补充😂

    作者回复: 好的 期待

    2021-08-09
    3
    2
  • 王子虾
    老师,有一个问题,tcp在调用listen的时候,有全连接队列的概念,一般上限是128。但是问题是,我们比如实现单机百万链接的时候,一个server端的源组(server_ip+port),比如有65535个client,那会不会受限于这个全连接队列?

    作者回复: 会,但 linux可以修改 /proc/sys/net/core/somaxconn

    2022-04-09
  • ifelse
    nice

    作者回复: good

    2022-02-25
  • GeekCoder
    能讲讲epoll吗?

    作者回复: 本课程是os实现课程 不会讲到这个

    2021-10-24
  • pedro
    这里有一篇三次握手的源码图解:https://mp.weixin.qq.com/s/vlrzGc5bFrPIr9a7HIr2eA

    作者回复: 谢谢 老铁

    2021-08-09
  • MacBao
    服务器端处于listen状态,客户端connect发起TCP三次握手?
    2021-08-09
    1
收起评论
显示
设置
留言
9
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部