关于Socket编程中的地址组和协议组
2007-08-27 14:45
232 查看
原文请参见 http://casit.blogbus.com/logs/7748763.html
写socket程序,恐怕都是从socket函数开始的。但是对这个函数却很少深入探究。在此我给出一些我的分析结果。
先看原型: SOCKET socket(int af,int type,int protocol); //Windows
int socket(int domain, int type, int protocol); //Linux
除 了返回值不同外,第一个参数还是不同的。我们注意到,Windows下第一个参数是af(address family),而Linux下则是domain(protocol family)。而看参数的值,也有AF_*和PF_*之别。那么这两者之间究竟有没有区别呢?
地址族和协议族究竟是否为一码事呢?很显 然,他们应该含义是不同的。比如,Internet协议族(v4)里分TCP、UDP等协议,但是他们统属Internet协议族(PF_INET)。而 对应的,他们的地址也是IPv4地址。所以其地址族为(AF_INET)。但是无论看Win下还是Linux下的定义就会发现,所有的都是 (#define PF_INET AF_INET),也就是说,地址族和协议族的值永远是相等的。这似乎显得多此一举了,既然值都是一样的,为什么要定义两套呢?
我们回想一 下socket函数所做的工作:创建一个插口!仅仅是创建一个插口。在这个时候,这个插口应该是还没有和任何地址绑定,直到你显示调用bind或是 connect(connect会自动将插口绑定到一个本地地址)。那么也就是说,socket调用的时候,根本还没有地址什么事情。看了Linux的源 代码会进一步发现,Linux下,网络协议被映射成多个域(domain),也就是socket函数中的domain,这个域是协议域,而不是地址域。所 以,我们看Linux的man手册中,对domain函数的可选参数的介绍都是PF_开头的。但是令人迷惑的是,在Win的MSDN中,明确给出的可选参 数都是AF_开头的,并且也明确说了,第一个参数是“地址域”参数,而不是“协议域”。那么这里有两种可能,一:Win下认为地址域和协议域是一码事; 二:Win在创建一个插口的时候,是将其绑定到一个地址域,而不是协议域(Win下没有协议域的概念)。这两种解释都是猜测,没有什么根据。也懒得查资料 了。呵呵
那么,我们该怎么办?就目前来看,很好办,无论你用AF_*还是PF_*都是可以的,因为他们都是对等的。但是严谨的做法似乎应该是这样的:
1、win下,一律使用AF_*来创建插口
2、Linux下,一律使用PF_*来创建插口
以 上的分析,似乎有点本本主义,但是对于我们常用的函数,可能很少去深入探究其每一个细节,因为我们所做的工作基本都是符合2/8原则的。可是,就如同,很 少有人检查strcpy的返回值一样,因为大家都认为这样的函数“以常规的用法”一定会成功。写这篇文章,也是想提醒自己,对每一个细节都不应该放过。
写socket程序,恐怕都是从socket函数开始的。但是对这个函数却很少深入探究。在此我给出一些我的分析结果。
先看原型: SOCKET socket(int af,int type,int protocol); //Windows
int socket(int domain, int type, int protocol); //Linux
除 了返回值不同外,第一个参数还是不同的。我们注意到,Windows下第一个参数是af(address family),而Linux下则是domain(protocol family)。而看参数的值,也有AF_*和PF_*之别。那么这两者之间究竟有没有区别呢?
地址族和协议族究竟是否为一码事呢?很显 然,他们应该含义是不同的。比如,Internet协议族(v4)里分TCP、UDP等协议,但是他们统属Internet协议族(PF_INET)。而 对应的,他们的地址也是IPv4地址。所以其地址族为(AF_INET)。但是无论看Win下还是Linux下的定义就会发现,所有的都是 (#define PF_INET AF_INET),也就是说,地址族和协议族的值永远是相等的。这似乎显得多此一举了,既然值都是一样的,为什么要定义两套呢?
我们回想一 下socket函数所做的工作:创建一个插口!仅仅是创建一个插口。在这个时候,这个插口应该是还没有和任何地址绑定,直到你显示调用bind或是 connect(connect会自动将插口绑定到一个本地地址)。那么也就是说,socket调用的时候,根本还没有地址什么事情。看了Linux的源 代码会进一步发现,Linux下,网络协议被映射成多个域(domain),也就是socket函数中的domain,这个域是协议域,而不是地址域。所 以,我们看Linux的man手册中,对domain函数的可选参数的介绍都是PF_开头的。但是令人迷惑的是,在Win的MSDN中,明确给出的可选参 数都是AF_开头的,并且也明确说了,第一个参数是“地址域”参数,而不是“协议域”。那么这里有两种可能,一:Win下认为地址域和协议域是一码事; 二:Win在创建一个插口的时候,是将其绑定到一个地址域,而不是协议域(Win下没有协议域的概念)。这两种解释都是猜测,没有什么根据。也懒得查资料 了。呵呵
那么,我们该怎么办?就目前来看,很好办,无论你用AF_*还是PF_*都是可以的,因为他们都是对等的。但是严谨的做法似乎应该是这样的:
1、win下,一律使用AF_*来创建插口
2、Linux下,一律使用PF_*来创建插口
以 上的分析,似乎有点本本主义,但是对于我们常用的函数,可能很少去深入探究其每一个细节,因为我们所做的工作基本都是符合2/8原则的。可是,就如同,很 少有人检查strcpy的返回值一样,因为大家都认为这样的函数“以常规的用法”一定会成功。写这篇文章,也是想提醒自己,对每一个细节都不应该放过。
相关文章推荐
- 同一端口是否可以绑定到多个IP上(关于Socket编程中地址与端口绑定那些事)
- 关于网络协议和socket编程基本概念
- Socket编程实践(13) --UNIX域名协议
- 基于TCP/IP和UDP协议的socket编程结构解析
- Net网络通讯编程[利用Socket实现字串、文件、序列化对象传输]--前面6篇博文全部源代码下载地址
- Socket编程-UDP协议(C#)
- 关于linux socket 编程 端口复用的理解
- 关于socket编程中的INADDR_ANY
- 关于socket与网络协议的整理
- 关于UNIX Domain Socket 编程
- 【网络编程笔记】简单的TCP协议 socket编程(C语言版服务器和客户端)
- ACE与ASIO之间关于Socket编程的比较
- 关于Socket通讯时通讯协议的制定
- 网络层、传输层、应用层、端口通信协议编程接口 - http,socket,tcp/ip 网络传输与通讯知识总结
- 关于Socket编程项目之后经验谈
- Socket编程中如何发送结构体,拼接多次接收消息及获取通信双方地址
- ACE与ASIO之间关于Socket编程的比较
- 关于cocos2dx网络编程http,udp,tcp,socket
- QT-Socket编程之模拟TCP五层协议解/封装
- Socket编程实践(13) --UNIX域协议