深入Linux网络子系统02:bind()到底做了什么?

Linux——网络通信 包括多种机制,如管道、消息队列、信号、共享内存和信号量。这些机制都依赖于Linux内核提供的支持,用于实现不同进程之间的数据交换和同步。然而,这些通信方式在本地进程间通信中非常有用,但无法直接用于跨机器间的通信。 阅读详情


前言

上一篇文章我们讲了socket()系统调用:它仅仅在内核创建一个空的套接字对象,分配 fd、初始化sock结构体等等,但是没有 IP、没有端口,没有任何地址信息,内核不知道要从哪个网卡、哪个端口收发数据。今天继续系列第二篇,拆解函数bind():

  1. bind到底干了什么?
  2. 为什么客户端通常不需要 bind?
  3. 内核端口绑定原理?

一、一行代码,看懂入口

1.1 函数原型

 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数详解:

  • sockfd:socket()创建的套接字文件描述符
  • addr:地址结构体,包含协议族、IP、端口
  • addrlen:地址结构体长度

返回值:

  • 成功:返回0
  • 失败:返回-1,并设置errno

1.2 极简示例(TCP 服务端)

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8080);
// 绑定所有网卡
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

int ret = bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

二、调用 bind()时,内核默默做了什么事情

2.1 关键结构体

// struct inet_hashinfo 是 Linux 内核网络协议栈中用于管理 TCP/UDP 连接查找的关键数据结构
struct inet_hashinfo 
{
    // 所有建立连接的socket,哈希key:四元组
	struct inet_ehash_bucket	*ehash;
    // 所有绑定端口的socket,哈希key:端口
	struct inet_bind_hashbucket	*bhash;
    // 所有监听scoket,哈希key:端口
	struct inet_listen_hashbucket	listening_hash[INET_LHTABLE_SIZE];
};

四元组:网络通信中唯一标识一条 TCP 连接的四个要素。

  • 源 IP 地址(Source IP)
  • 源端口号(Source Port)
  • 目的 IP 地址(Destination IP)
  • 目的端口号(Destination Port)

有时也会提到五元组,就是在四元组基础上加上传输层协议号(TCP/UDP),用于区分不同协议的连接。

2.2 bind()完整执行链路

socket的相关函数都在net\socket.c中,bind()方法主要内容如下:

SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
{
	struct socket *sock;
	struct sockaddr_storage address;
	int err, fput_needed;
	// 由 fd 获取 监听的 socket
	sock = sockfd_lookup_light(fd, &err, &fput_needed);
	if (sock)
	{
		// 将用户态地址拷贝到内核中
		err = move_addr_to_kernel(umyaddr, addrlen, &address);
        // 实际调用 inet_stream_ops 中的 inet_bind(详见第一篇文章,socket已绑定操作集)
		err = sock->ops->bind(sock, (struct sockaddr *)&address, addrlen);
	}
	return err;
}

inet_bind主要做的工作包括:

int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
    // 确保 sock 处于 TCP_CLOSE 状态且尚未绑定过端口
    if (sk->sk_state != TCP_CLOSE || inet->inet_num)
		goto out_release_sock;
    // inet_rcv_saddr:收包是谁
    // inet_saddr:发包是谁
    // 在普通单播 bind 时,它们是同一个值,此时确定了四元组中的源IP
    inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr;
    // 绑定端口,TCP协议实际调用的是 inet_csk_get_port
    sk->sk_prot->get_port(sk, snum);
    // 到这里,四元组中的 源地址 源端口 确定好了
    inet->inet_sport = htons(inet->inet_num);
	inet->inet_daddr = 0;
	inet->inet_dport = 0;
}

rcv_saddr** 和 saddr 的双地址设计:**

字段用途场景差异
inet_rcv_saddr收包时用于四元组匹配始终等于用户 bind 的地址
inet_saddr发包时填充 IP 源地址多播/广播时置 0,由出包路径决定

inet_csk_get_port比较复杂,主要内容总结如下:

  1. 端口分配:
  • 若用户指定了端口,则尝试绑定指定的端口号。
  • 若用户没指定端口或指定端口为0,则从系统临时端口范围(由 ip_local_port_range 控制)内自动选取一个可用的端口。
  1. 冲突检测与绑定:
  • 通过查找哈希表(bhash),检查目标端口是否已被占用。
  • 若端口已被其他套接字使用,则根据是否允许地址复用(SO_REUSEADDR / SO_REUSEPORT)以及绑定的具体地址(INADDR_ANY 或特定 IP)判断是否冲突。
  • 若无冲突,则将当前套接字加入bhash,并更新套接字的本地端口字段。

三、总结

  1. socket()创建空白套接字;bind()为套接字分配本地 IP + 端口,在内核建立地址映射
  2. bind 内核流程:状态校验→拷贝地址→端口冲突检查→填充 socket 地址→注册bhash
  3. 服务端必须 bind 固定端口,方便客户端访问;客户端默认依靠 connect 触发隐式绑定
Qt网络编程避坑指南:QUdpSocket的bind()、writeDatagram()你真的用对了吗? 本文深入探讨了Qt网络编程中QUdpSocket的常见使用误区,特别是bind()和writeDatagram()方法的正确用法。针对UDP通信中的IPv4/IPv6绑定选择、大数据发送、数据接收处理等关键问题提供了实用解决方案,帮助开发者避免常见陷阱,提升网络编程效率。 阅读详情

相关推荐

C语言网络编程实战:用socket()和bind()快速搭建本地TCP服务器(附完整代码)

本文通过实战案例,详细讲解了如何使用C语言进行网络编程,从零开始搭建一个本地TCP服务器。文章核心围绕socket()和bind()函数展开,涵盖了套接字创建、地址绑定、端口监听以及实现一个简易回声服务的完整流程,并提供了可直接编译运行的完整代码示例,帮助开发者深入理解TCP协议与底层网络通信机制。

redis7keeper的博客 1078

Linux 网络子系统分析4

Linux 网络子系统分析4(基于Linux6.6)---INET连接之bind & listen分析

ListQ的博客 851

bind()函数的概念和使用案例

bind()的概念和使用案例

weixin_42108533的博客 595

socket编程之bind()

socket编程之bind()

qq_55537010的博客 8409

一篇文章将三极管讲透:三极管从原理到应用,从参数到特性,从入门到精通

晶体三极管(Transistor)是一种半导体电子器件,也是电子工程中最基本的元件之一。它有三个区域,分别是P型半导体,N型半导体和P型半导体,从而形成PNP型晶体三极管或者NPN型晶体三极管。

学习帮的博客 9万+

卡方检验的隐藏逻辑:为什么正态分布的平方和如此重要?

本文深入探讨了卡方检验的核心逻辑,揭示了正态分布平方和在统计检验中的重要性。通过分析卡方分布与伽马分布的关系,以及实际应用案例,帮助读者理解卡方检验的原理、局限及高级应用场景,为数据分析提供有力工具。

3a9bq4r8t2y的博客 208

Linux网络编程,bind:error:Cannot assign requested address,Ubuntu网络桥接

一:问题:刚开始学习Linux网络编程,第一次使用bind函数出现Cannot assign requested address,错误。在网上找了很多帖子但是都没有解决。 二: 问题一:也就是网上大部分说的:客户端频繁的连服务器,由于每次连接都在很短的时间内结束,导致很多的TIME_WAIT,以至于用光了可用的端 口号,所以新的连接没办法绑定端口,即“Cannot assign requested address”。是客户端的问题不是服务器端的问题。 方法一:通过netstat -nap查看当前的状态,的

weixin_44261839的博客 1万+

还原 Windows 环境变量的默认值

有时候,我们可能需要还原环境变量的默认值,以修复可能的配置问题或恢复系统的正常运行。如果您只想还原某个特定的环境变量,可以跳过删除其他变量的步骤,仅删除需要还原的变量即可。在“环境变量”对话框中,继续向下滚动到“系统变量”部分。请注意,在执行以下步骤之前,您应该备份当前的环境变量设置,以便在需要时可以还原。在删除所有需要还原的环境变量后,点击“确定”按钮关闭“环境变量”对话框。在“用户变量”部分,选择需要还原的变量,然后点击“删除”按钮。在“高级”选项卡下方的“环境变量”部分,点击“环境变量”按钮。

PvDeveloper的博客 6342

深入Linux网络子系统01:socket() 到底做了什么?

Linux网络编程:socket()函数内核实现解析 本文通过分析socket()函数的内核实现过程,揭示Linux网络子系统的核心工作机制。当用户调用socket()创建TCP套接字时,内核主要完成以下操作: 结构体初始化:通过sock_alloc()分配socket结构体,sk_alloc()分配sock结构体,形成socket(用户层接口)与sock(内核协议栈实体)的对应关系。 协议栈注册:根据协议族(如AF_INET)找到注册的inet_family_ops操作集,调用其create方法(inet

LinuxTechNote的博客 335

Hermes 教程 05:多 Agent 编排

本文介绍了Hermes v0.13.0中的四种多Agent协作模式:1)delegate_task快速子任务模式,适合2-3个独立并行任务;2)spawn子Agent模式,实现零成本并行多步流水线;3)tmux交互子Agent模式,支持长期自主任务;4)全新Kanban看板系统,提供持久化AI团队协作框架。各模式在隔离级别、时长、工具访问和适用场景上存在差异,其中spawn模式通过独立上下文窗口实现零上下文成本。文章详细说明了每种模式的使用方法、限制条件和典型应用场景,并提供了具体代码示例和可视化流程图。K

程序猿_三产 537

如何用DeepSeek写年底工作总结?——从入门到精通的全流程指南

AI助手DeepSeek如何高效撰写工作总结 摘要:本文介绍如何利用DeepSeek智能AI助手高效完成工作总结写作。工作总结具有结构固定、语言规范、内容数据化三大特性,而DeepSeek的结构化生成、风格适配、数据整合和迭代优化四大核心能力与之完美匹配。文章提出"准备-搭架-填充-优化"四步工作法:1)精准输入岗位、时间范围等核心信息;2)先搭建逻辑清晰的提纲框架;3)分模块填充具体内容,突出数据与案例;4)通过风格润色和细节补充进行优化。通过合理运用多模态材料处理能力,DeepSee

通俗易懂学IT 289

Linux网络编程socket bind() 函数

bind()函数 名称:         bind  -- 给socket 绑定一个地址名称 原型:         #include         int bind(int socket, const struct sockaddr* address, socklen_t address_len);    描述:         bind()函数给一个 无名socket

yang07cs的专栏 1486

构建具有预测维护能力的AI Agent

随着工业4.0的推进,工业设备的复杂性和自动化程度不断提高,设备的稳定运行对于企业的生产效率和经济效益至关重要。预测维护作为一种先进的设备维护策略,能够通过对设备状态的实时监测和分析,提前预测设备故障,从而避免设备意外停机,降低维护成本。本文的目的是详细阐述如何构建具有预测维护能力的AI Agent,涵盖从数据采集、处理、模型训练到实际应用的整个流程,为企业和开发者提供全面的技术指导。本文将按照以下结构进行组织:首先介绍核心概念与联系,包括预测维护和AI Agent的基本原理和架构;

2501_92132293的博客 943

关于Linux 网络编程bind()和connect()的理解

关于Linux 网络编程bind()和connect()的理解 band()绑定的是什么 connect()连接的是什么 band()绑定的是什么band()绑定的是自己本机的ip和端口 1、采用TCP通信时,客户端不需要bind()他自己的IP和端口号,而服务器必须要bind()自己本机的IP和端口号; 2、若采用UDP通信时(这里是有客户端和服务器之分才这么说的,若是指定特定端口的UDP对等

yrx0619的专栏 1429

Android 12 系统横屏时,开机动画有两秒显示不全

平板系统默认横屏时,开机会旋转90度,显示的分辨率WxH,会变成HxW.但又会很快被SurfaceFlinger的SurfaceFlinger::processDisplayChanged 娇正。所以为了保险,可以在开机动画没结束之前,禁止旋转事件。在Android 12 产品定制化开发中,由于系统默认方向为竖屏,平板电脑要横屏显示。系统在开机时,有时因为旋转,会出现动画只显示一部分。

448313096@qq.com 1183

飞牛fnNAS搭建Web网页版OFFICE(WPS)软件

本文介绍了如何在飞牛NAS上通过Docker容器部署WPS Office办公软件。主要内容包括:启用Docker服务、准备项目文件夹结构、使用Compose方式构建容器、解决端口冲突问题、配置中文输入法和字体库,以及通过ZeroTier实现远程访问。文章详细说明了每个步骤的操作方法,包括容器启动、输入法设置、字体添加和文件存储位置配置。最后还介绍了使用ZeroTier内网穿透技术实现远程访问NAS上WPS服务的方法,让用户可以在不同设备上随时编辑NAS中的文件。整个部署过程完整清晰,为NAS用户提供了便捷的

dgnankai的专栏 1702

Linux bind 命令详解:将一个名称与一个 IP 地址进行关联,或者将一个特定的网络接口绑定到某个网络设备上

在 Linux 系统中,bind命令用于将一个名称与一个 IP 地址进行关联,或者将一个特定的网络接口绑定到某个网络设备上。这通常与域名解析(DNS)有关,因为bind也用于启动和配置 DNS 服务器。bind还常用于网络配置中,特别是在配置 TCP/IP 网络时,bind用于让应用程序将其套接字(socket)绑定到指定的 IP 地址和端口。比如,在运行一个 Web 服务器时,你可以使用bind将该服务器的监听端口绑定到特定的 IP 地址和端口。然而,在 Linux 系统中,bind。

yangchuang111213的博客 2368

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Linux bind函数详解

int bind(int sockfd,const struct sockaddr * addr,socklen_t addrlen); bind()函数用于服务器端,服务器的网络地址和端口号通常固定不变,客户端得知服务器的地址和端口号以后,可以主动向服务器请求连接。因此服务器需要调用bind()绑定地址。bingd()函数定义在sys/socket.h头文件中; sockfd表示socket文...

qq_42861208的博客 6816

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

socket: bind()绑定套接字函数、connect()建立连接函数

//bind() 函数原型 int bind(int sock, struct sockaddr *addr, socklen_t addrlen); //Linux int bind(SOCKET sock, const struct sockaddr *addr, int addrlen); //Windows //connect() 函数原型 int connect(int sock,...

qq_33373173的博客 695

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

【Socket网络编程】1.bind()和 INADDR_ANY 解析

bind()和 INADDR_ANY 解析 linux网络编程之UDP通信 http://blog.sina.com.cn/s/blog_c2f250bd0101ii14.html 该博客讲了tcp和udp的一些常用参数 bind()解析 当使用socket()创建套接字后,只赋予其所使用的协议,并未分配地址。 在接受其它主机的连接前,必须先调用bind()为套接字分配一个地址。 bind() 一般用于服务器端,将一个套接字与一个套接字地址结构相关联,比如,关联一个指定的本地端口和IP地址。 bind()

u011754972的博客 3000

Linux使用Bind搭建DNS服务: 从菜鸟到网络大神的进阶之路[收藏级]

本文介绍了在局域网环境中使用BIND软件搭建DNS服务的方法。主要内容包括: BIND简介:BIND是ISC开发的开源DNS服务软件,提供named服务程序处理DNS查询,支持正向解析(域名转IP)和反向解析(IP转域名)。 安装配置: 通过包管理器安装bind9 修改主配置文件named.conf,设置日志、端口、访问控制等 配置正向解析区域文件,包含SOA、NS、A等记录类型 主从架构: 主服务器配置区域传输权限 从服务器同步主服务器数据 解决Ubuntu系统中AppArmor权限问题 测试验证: 使用

https://ophome.blog.youkuaiyun.com,在IT行业有多年的工作经验,尤其是在Python、Linux、负载均衡、Nginx和服务器运维等领域。 1493

深入解析Linux网络编程之bind函数:从基础到实践的艺术

本文深入解析Linux网络编程中的bind()函数,从基础概念到实践应用。首先介绍了bind()的函数原型、参数解析和错误处理,详细讲解了地址结构体的演变过程和字节序转换方法。然后通过TCP服务器示例展示了bind()的实际应用,包括多IP绑定策略和端口重用技术。最后讨论了性能影响因素并给出最佳实践建议,如严格检查返回值、合理选择端口范围等。全文系统性地阐述了bind()函数在网络编程中的核心作用和使用技巧。

软件科学-郝学胜 848

Linux网络编程——socket、bind、listen、accpet、connect、read和write

socket网络编程,总体步骤清晰。服务端所需要用到socket()、bind()、listen()、accept();客户端所需要用到socket()、connect();两者数据传输均需要read()、write()。 bind()中绑定IP地址和端口号,需要使用到内核指定结构体,需要理解接受;connect()和bind()使用方法相同。网络编程需要知道大端和小端字节序的转换,以及网络字节序和主机字节序的获取。

Jackice_Lee的博客 2341

《Linux 中 TCP 连接的 “本地地址绑定”:bind () 函数与多网卡环境的配置要点》

在多网卡环境中,显式使用。

2501_93892580的博客 1070

Linux基于Bind9搭建dns服务器

Bind9简介 Bind是Berkeley Internet Name Domain Service的简写,它是一款实现DNS服务器的开放源码软件。Bind已经成为世界上使用最为广泛的DNS服务器软件,目前Internet上半数以上的DNS服务器都是用Bind来架设的,已经成为DNS中事实上的标准。 bind历史 BIND4版本,BIND包最初是在 1980 年代初在加州大学伯克利分校作为研究生项目在美国国防高级研究项目管理局 (DARPA)的资助下编写的。BIND 到 4.8.3 的版本由加州大学伯克

IT 1万+

理解 Linux 动态库加载:LD_LIBRARY_PATH

flyfish

二分掌柜的 399
上一篇: 深入Linux网络子系统01:socket() 到底做了什么?
下一篇: 深入Linux网络子系统03:调用 listen 之后,内核发生了哪些事?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值