继上篇
TCP/IP FAQ(1),本篇涵盖了域和协议、IP编址、插口、原始IP、unix域方面的问题与解答。
【Domain & Protocol】
1. 什么是域,它和协议有什么关系?
域可以理解为一种容纳协议的空间,它的存在便于了协议的分类;域和协议是集合与元素的关系,一个域中的每个协议使用同类地址,并且每种地址只被一个域使用,一个域能由协议族或地址族常量唯一标识。
2. TCP/IP中有哪些域及其协议?
internet、iso、route、ccitt、imp、network systems和unix,其中internet域含有ip,icmp,igmp,tcp和udp五种协议,unix域用于ipc通信。
3. 哪些地方会用到域?
一个网络层协议必须分用输入数据报,并交给相应的传输层协议,由于域包含了协议族,因此必须从对应的域中找到合适的协议去处理。例如IP对应的域为internet,这个域对应的协议族为inetsw,当收到IP数据报时,就从inetsw中找到对应的传输层协议去输入处理。
【IP Addressing】
1. IP地址有哪几类?
分为5类,A、B和C类用于单播;D类用于多播;E类用于实验。
2. sockaddr和sockaddr_in有什么区别联系?
sockaddr是一种通用的用于接口编址信息的结构,它将硬件与协议的地址细节相对于接口层隐藏起来,成员依次为sa_len、sa_family和sa_data,而sockaddr_in成员依次为sin_len、sin_family、sin_port、sin_addr和sin_zero。它们的前两个成员其实是一样的,只是命名不同,而sockaddr_in中的sin_port标识传输层的端口,sin_addr标识IP层的地址,所以它是Internet协议的专用接口编址结构,sin_zero仅为填充用,因为sockaddr_in长度不应小于sockaddr。
3. 插口编址结构允许的最大长度是多少?
sockaddr最后一个成员是可扩展的,这是C语言的通用技术,因为其第一个成员为u_char类型,所以最大长度是255。
4. 一个接口可以配置多个IP地址,是怎么实现的?
ifaddr表示通用的接口地址,ifnet表示接口,它有个类型为ifaddr*的if_addrlist成员,表示当前接口上的地址链表。in_ifaddr表示Internet协议专用的接口地址,而IP属于Internet协议,因此用in_ifaddr表示,所有的IP地址组成一个类型为in_ifaddr*的链表。当增加一个IP地址时,就需要插入这两个链表中;当删除一个IP地址时,就需要从它们当中移除。
5. 为什么配置IP主机地址和网络掩码可以是独立的?
因为它们使用不同的命令实现,前者用SIOCSIFADDR,后者用SIOCSIFNETMASK。当配置IP主机地址时,如果没有指明网络掩码,那么网络掩码被设置成默认的。
6. 为什么访问IP接口地址使用的是UDP插口而不是原始IP插口?
只有超级用户用程才能创建原始IP插口,而通过UDP插口,任何用户进程都能查看接口配置。
【Socket】
1. 为什么会存在插口层?
从概念上讲,tcp/ip协议栈划分为链路、网络、传输和应用4层;但从实现上讲,在应用层和其下层中间,引入了一个插口层,作为进程和内核通信的桥梁,主要功能是将进程发送的与协议有关的请求映射到产生插口时指定的与协议有关的实现,从而屏蔽了不同协议处理的细节。
2. 为什么服务器进程总是要调用bind,客户进程能调用它吗?
bind将一个本地地址同一个插口相关联,客户进程需要同一个已知地址建立连接或发送数据报到已知地址,如果不调用bind,服务器进程就无法在某个已知地址上接受TCP连接或接收UDP数据报。客户进程也能调用bind,这样便可以由应用程序而非内核来选择一个本地地址,其结果是只能接收目的地址为被绑定地址的数据包,但通常不必调用bind,因为内核会自动决定外出地址和临时端口。
3. 对于tcp和udp协议的插口,调用connect有什么区别联系?
共同点是设定插口的外部地址(插口的地址存储在相关的协议控制块中),不同点如下
1)tcp:与远端系统进行3次握手交互,如果插口是非阻塞的且连接正在进行中,那么返回EINPROGRESS,下次再调用则返回EALREADY;如果连接成功,无论是否阻塞,那么下次再调用会返回EISCONN;如果连接失败,那么下次再调用,则重新开始三次握手。
2)udp:没有3次握手交互,直接设定外部地址,无论插口是否阻塞,调用会立即返回,多次调用则会替换老的外部地址。发送数据必须使用write或目的地址为空的sendto,若sendto目的地址非空,则返回EISCONN。如果没有事先调用connect,那么调用目的地址为空的sendto则会返回ENOTCONN。
4. 什么情况下调用close会阻塞?
连接已建立且设置了SO_LINGER选项并延时值非零的阻塞插口。
5. 插口IO有哪些系统调用?
发送有write、writev、sendto和sendmsg,接收有read、readv、recvfrom和recvmsg。注意,send和recv是库函数而非系统调用,前者调用sendto实现,后者调用recvfrom实现。
6. write、writev、read、readv与sendto、sendmsg、recvfrom、recvmsg有什么不同?
1)前面4个适合于任何描述符,而后面4个只能用于插口。
2)前面4个不支持标志,而后面4个支持。
3)前面前2个不支持目的地址、后2个不支持源地址,而后面前2个支持目的地址、后2个支持源地址。
4)前面4个不支持控制信息,而后面第2个和第4个支持。
7. 如何断开已连接的udp插口,允许调用sendto向其它主机发送数据?
由于系统并没有提供形如disconnect的断连API,但connect内部实现是先断连,再调用对应协议的PRU_CONNECT请求处理,因此向connect传递无效的外部地址结构(如IP=0.0.0.0,Port=0),虽然这样会导致结果失败,但先前的断连成功,对应pcb的外部地址被设为INADDR_ANY,所以调用sendto就不会返回EISCONN。
【Raw IP】
1. 怎么使用原始IP,它有哪些用途及应用?
创建SOCK_RAW类型的原始插口,就能使用原始IP机制,它有下列用途:
1)发送和接收ICMP和IGMP报文,如ping程序和多播路由守护程序。
2)构造自己的IP首部,如路由跟踪程序。
3)设计基于IP的新的传输层协议,如gated程序。
2. 协议值为PROTOCOL_RAW(255)的原始插口能收到什么类型的IP数据报?
由于255是非零的保留值,这样的IP数据报在网络中不会存在,原始IP输入处理协议比较测试失败,因此收不到任何类型的IP数据报。
3. 协议值为0的原始插口能收到什么类型的IP数据报?
由于协议值为0,原始IP输入处理忽略了协议比较测试,因此能收到任何类型的IP数据报。
4. 如何处理收到的IP数据报?
遍历Internet PCB表,依次从协议值、本地地址和外部地址三项来比较IP数据报和每个PCB,将IP数据报复制追加到所有匹配的PCB对应的插口缓存中,并唤醒等待的进程。
5. 如何发送数据?
先填充IP首部,如果未设置IP_HDRINCL选项,那么由内核填充,否则由应用程序在发送前填充,再交给IP协议输出处理。
6. 内核何时会调用原始输入?
当收到的协议类型为除IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP和IPPROTO_IGMP外的IP数据报时调用。
【Unix domain】
1. 使用unix域的原因有哪些?
1)当通信双方在同一主机上时,使用unix域插口的速度比tcp和udp插口要快很多。
2)支持同一主机进程间传递描述符。
2. unix域和internet域有什么不同?
1)编址结构不同:前者是sockaddr_un,与文件系统路径名关联,而后者是sockaddr_in,与IP地址和端口关联。
2)协议控制块不同:前者是unpcb,没有全局的pcb链表,而后者是inpcb,有全局的pcb双向循环链表。
3. 如果一个unix域服务器在bind后unlink了被绑定的路径名,会发生什么情况?
因为connect内部实现查找路径名失败,所以连接失败,但listen会成功,因为bind会创建新的vnode和pcb关联,且PRU_LISTEN请求实现只检查vnode是否为空。
4. 如果一个unix域服务器在终止时没有unlink被绑定的路径名,会发生什么情况?
因为connect内部实现虽能找到路径名但找不到相关的插口,所以连接被拒绝。
5. 系统调用socketpair和pipe有什么区别联系?
共同点是使用unix域,即socket调用第1参数为AF_UNIX,不同点如下
1)前者是双工的,因为两个插口标志都为读写,且它们的pcb相互指向对方;后者是单工的,因为一个插口标志为只读,另一个为只写,写插口的pcb指向读插口的pcb。
2)前者支持数据报和流式插口,后者仅支持流式插口。
6. unix域是怎么实现传递描述符的?
描述符存储在控制信息cmsghdr内,cms_level=SOL_SOCKET且cms_type=SCM_RIGHTS,unix域的发送请求实现将描述符转换为file指针,这个过程叫内部化,接收请求实现把file指针转换为最小的没有使用的描述符,这个过程叫外部化。
posted on 2013-09-03 15:52
春秋十二月 阅读(2346)
评论(1) 编辑 收藏 引用 所属分类:
Network