接上篇《socket地址绑定》
三、根据不同的协议来完成绑定
上面代码中的第3步是根据应用程序在创建socket时传递到内核的协议域及socket类型来决定调用采用哪个方法,具体可以参考
创建socket
一文,这里不再赘述;下面以AF_IENT及SOCK_STREAM为例来说明绑定的过程;
1、调用链:
net/Socket.c:sys_bind()->net/ipv4/Af_inet.c:inet_bind();
2
、inet_bind()逻辑:
1) 地址类型检查
chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
if (!sysctl_ip_nonlocal_bind &&
!inet->freebind &&
addr->sin_addr.s_addr != htonl(INADDR_ANY) &&
chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST &&
chk_addr_ret != RTN_BROADCAST)
goto out;
inet_addr_type()函数根据设置的ip地址检查其类型:
static inline unsigned __inet_dev_addr_type(struct net *net,
const struct net_device *dev,
__be32 addr)
{
……
if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr))
return RTN_BROADCAST;
if (ipv4_is_multicast(addr))
return RTN_MULTICAST;
……
local_table = fib_get_table(net, RT_TABLE_LOCAL);
if (local_table) {
ret = RTN_UNICAST;
if (!local_table->tb_lookup(local_table, &fl, &res)) {
if (!dev || dev == res.fi->fib_dev)
ret = res.type;
fib_res_put(&res);
}
}
return ret;
}
其中:
a.
ipv4_is_zeronet()用于检查地址的高8位是否为0,即地址是否为0.x.x.x,这类地址称为零网地址,零网地址也属于广播地址;
b.
ipv4_is_lbcast()用于检查地址是否是广播地址(广播地址有两种,一种是有限广播,即255.255.255.255,它不会被路由但是会发送到物理网段上的所有主机;另一种是直接广播,该类地址的主机字段为255,如192.168.1.255,该广播会路由到192.168.1网段的所有主机上);这里只是检查是否是有限广播地址;
c.
ipv4_is_multicast()用于检查地址是否是多播地址,即224.x.x.x的D类地址;
当ip地址既不是多播,也不是广播时,需要通过查找路由表来确定地址的类型(关于路由表,后面再叙述);
拿到地址类型后,inet_bind()函数会检查地址是否是单播、多播或广播地址;否则就直接出错并返回;
2) 端口范围检查
snum = ntohs(addr->sin_port);
if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
goto out;
/* Sockets 0-1023 can't be bound to unless you are superuser */
#define PROT_SOCK 1024
这里检查如果端口小于1024,且具有超级用户权限,否则直接出错并返回;
3) 设置源地址和接收地址
if (sk->sk_state != TCP_CLOSE || inet->num)
goto out_release_sock;
inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr;
if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
inet->saddr = 0; /* Use device */
这里先检查sock的状态,如果不是TCP_CLOSE或端口为0,则出错返回(这里也映射到创建socket时要将sock结构体变量的状态设置为TCP_CLOSE上了);
如果地址类型是多播或广播,则源地址设置为0,而接收地址为设置的ip地址;
4) 检查端口是否被占用
if (sk->sk_prot->get_port(sk, snum)) {
inet->saddr = inet->rcv_saddr = 0;
err = -EADDRINUSE;
goto out_release_sock;
}
这里根据创建socket协议族初始化时设置的sk_prot来判断端口是否被占用,如果被占用则直接出错返回;关于端口是否被占用,后面会有专门的一章来描述;
5) 初始化目标地址和端口
inet->sport = htons(inet->num);
inet->daddr = 0;
inet->dport = 0;
至此,地址绑定就完成了。
总结:
1、 根据文件描述符从进程描述符中取出相应的文件,再得到socket结构;
2、 检查ip地址的类型是否是单播、多播或广播;
3、 检查端口是否被占用;
分享到:
相关推荐
- 内核初始化过程中还包括网络协议栈的初始化,这是后续网络通信的基础。 - **内核文件解读** - **ELF文件格式** ELF(Executable and Linkable Format)是一种常见的可执行文件格式,用于存储编译后的程序代码和...
- 绑定地址:使用`bind()`函数将Socket绑定到特定的IP地址和端口号。 - 监听连接:对于服务器端,使用`listen()`函数设置最大连接队列长度,准备接受客户端连接。 - 接受连接:`accept()`函数用于接收客户端的...
Linux内核协议栈是操作系统核心的一部分,负责...通过深入研究Linux内核协议栈源码,不仅可以提升对网络协议的理解,还能为开发高效、稳定的网络应用提供理论支持。同时,这也有助于解决网络问题,提高系统的整体性能。
- `net/`目录下包含所有网络协议栈的源代码,如`tcp.c`处理TCP协议,`ipv4/`处理IPv4。 - `socket`层是用户空间与内核空间通信的接口,通过系统调用如`socket()`、`bind()`、`connect()`等实现。 - `sk_buff`...
### Linux2.6协议栈源代码解析(解密版) #### 概述 ...通过以上知识点的详细介绍,读者能够全面掌握Linux2.6内核网络协议栈的核心技术和实现细节,为进一步深入学习或实际项目开发提供坚实的基础。
1. **Linux内核网络模型**: - Linux网络模型分为五层:数据链路层、网络层、传输层、会话层和应用层,这与OSI七层模型相对应。 - 内核网络子系统的核心是网络协议栈,它负责数据包的接收、处理和发送。 2. **...
准备将readme.md作为笔记,记录linux内核网络协议栈源码剖析的过程 天2,2016年11月18日20:24:07 增加了对sys_socket(), sock_create, __sock_create(), inet_create()的完全注释 socket的创建过程已经完成,接下来...
《基于Linux网络协议栈实现及应用》这篇文献主要探讨了Linux操作系统中的TCP/IP协议栈的实现细节和网络编程模型。Linux以其强大的网络服务功能著称,支持多种网络协议,并能提供多种网络服务,如TCP/IP、IPX/SPX、...
3. **抽象数据结构**:在Linux协议栈的实现中,每一层都定义了一个抽象数据结构,如sk_buff(socket buffer),用于在不同协议层之间传递数据,提供统一的接口。这种设计使得上层协议可以透明地处理下层协议的具体...
- **TCP/IP协议栈**:熟悉TCP/IP协议栈中各层的功能与作用。 #### 4. 结构体 - **sockaddr**:用于表示套接字地址的通用结构体,包含地址族、端口号等信息。 - **sockaddr_in**:IPv4套接字地址的具体实现。 - **...
socket可以支持多种协议栈,如TCP/IP协议栈,使得不同主机间的进程能够通过网络进行通信。 #### 二、创建socket 创建socket是网络编程的第一步,主要通过`socket()`函数完成: ```c #include <sys/socket.h> int...
Linux Socket服务器编程是网络通信的基础,它涉及到操作系统内核、网络协议栈以及C语言编程。在本实例中,我们将创建一个简单的TCP服务器,它监听客户端的连接请求,并在连接建立后,向客户端发送特定的字符串并关闭...
`sock` 结构体与特定的网络协议紧密相关,每个协议都有对应的 `sock` 实现。下面是 `sock` 结构体的部分关键字段及其功能: - **`__sk_common`**:与 `inet_timewait_sock` 共享使用,这部分包含了基本的协议信息。...
2. **协议兼容性**:不同操作系统支持多种网络协议,这些协议的工作方式和地址格式各异,因此需要一种统一的通信机制。 **TCP/IP协议族**通过引入IP地址、传输层协议(如TCP或UDP)和端口号这三种元素的组合来唯一...
Linux Socket是操作系统提供的网络通信接口,它允许应用程序通过网络协议(如TCP/IP)进行通信。本文将深入探讨Linux Socket的工作原理,主要包括以下几个方面:socket发送数据的函数流程、sys_socket流程、以及...
在TCP/IP协议栈中,Socket提供了应用程序与网络协议的交互接口,使得应用程序可以通过Socket发送和接收数据。 2. **Windows Socket (Winsock)** Windows操作系统提供了Winsock API供开发者进行网络编程。Winsock...
6. 不同操作系统中的 SOCKET:包括 Windows Socket(Winsock)和 Linux Socket(BSD Socket)。 Windows Socket(Winsock): * 简称 Winsock,是在 Windows 环境下使用的一套网络编程规范,基于 BSD Socket API ...
这些API是用户程序与内核网络协议栈之间的桥梁,允许数据的发送和接收,以及对网络连接的管理等。 Linux内核通过统一的系统调用接口来处理所有与socket相关操作。在内核版本2.6.12中,系统调用的入口函数是`sys_...