导读:
7.5 重要的套接字函数
FreeBSD提供了与套接字相关的不同函数, “打开”一个套接字我们只 需要四个函数。 有时我们只需要两个。
7.5.1 客户端-服务器差异
典型情况中,以套接字为基础的数据通信一端是一个 服务器,另一端是一个 客户端。
7.5.1.1 通用元素
7.5.1.1.1 socket
这一个函数在客户端和服务器都要使用:socket(2)。它是这样被声明的:
int socket(int domain, int type, int protocol);
返回值的类型与open的相同,一个整数。 FreeBSD从和文件句柄相同的池中分配它的值。这就是允许套接字被以对文件相同的方式处理的原因。
参数domain告诉系统你需要使用什么 协议族。有许多种协议族存在,有些是某些厂商专有的,其它的都非常通用。协议族的声明在 sys/socket.h中
使用PF_INET是对于 UDP, TCP和其它网间协议(IPv4)的情况。
对于参数type有五个定义好的值,也在 sys/socket.h中。这些值都以 “SOCK_”开头。 其中最通用的是SOCK_STREAM, 它告诉系统你正需要一个 可靠的流传送服务(和PF_INET一起使用时是指 TCP)。
如果指定SOCK_DGRAM, 你是在请求 无连接报文传送服务(在我们的情形中是UDP)。
如何你需要处理基层协议 (例如IP),或者甚至是网络接口 (例如,以太网),你就需要指定 SOCK_RAW。
最后,参数protocol取决于前两个参数,并非总是有意义。在以上情形中,使用取值0。
未连接的套接字:对于函数socket我们还没有指定我们要连往什么其它(主机)系统。 我们新建的套接字还是 未连接的。
这是有意的:拿电话类比,我们刚把调制解调器接在电话线上。我们既没有告诉调制解调器发起一个呼叫,也不会应答电话振铃。
7.5.1.1.2 sockaddr
各种各样的套接字函数需要指定地址,那是一小块内存空间 (用C语言术语是指向一小块内存空间的指针)。在 sys/socket.h中有各种各样如 struct sockaddr的声明。 这个结构是这样被声明的:
/*
* 内核用来存储大多数种类地址的结构
*/
struct sockaddr {
unsigned char sa_len; /* 总长度 */
sa_family_t sa_family; /* 地址族 */
char sa_data[14]; /* 地址值,实际可能更长 */
};
#define SOCK_MAXADDRLEN 255 /* 可能的最长的地址长度 */
注意对于sa_data域的定义有些 不确定性。 那只是被定义为14字节的数组, 注释暗示内容可能超过14字节
这种不确定性是经过深思熟虑的。套接字是个非常强大的接口。多数人可能认为比Internet接口强不到哪里 ──大多数应用现在很可能都用它 ──套接字可被用于几乎 任何种类的进程间通信, Internet(更精确的说是IP)只是其中的一种。
sys/socket.h提到的各种类型的协议 将被按照 地址族对待,并把它们就列在 sockaddr定义的前面:
/*
* 地址族
*/
#define AF_UNSPEC 0 /* 未指定 */
#define AF_LOCAL 1 /* 本机 (管道,portal) */
#define AF_UNIX AF_LOCAL /* 为了向前兼容 */
#define AF_INET 2 /* 网间协议: UDP, TCP, 等等 */
#define AF_IMPLINK 3 /* arpanet imp 地址 */
#define AF_PUP 4 /* pup 协议: 例如BSP */
#define AF_CHAOS 5 /* MIT CHAOS 协议 */
#define AF_NS 6 /* 施乐(XEROX) NS 协议 */
#define AF_ISO 7 /* ISO 协议 */
#define AF_OSI AF_ISO
#define AF_ECMA 8 /* 欧洲计算机制造商协会 */
#define AF_DATAKIT 9 /* datakit 协议 */
#define AF_CCITT 10 /* CCITT 协议, X.25 等 */
#define AF_SNA 11 /* IBM SNA */
#define AF_DECnet 12 /* DECnet */
#define AF_DLI 13 /* DEC 直接数据链路接口 */
#define AF_LAT 14 /* LAT */
#define AF_HYLINK 15 /* NSC Hyperchannel */
#define AF_APPLETALK 16 /* Apple Talk */
#define AF_ROUTE 17 /* 内部路由协议 */
#define AF_LINK 18 /* 协路层接口 */
#define pseudo_AF_XTP 19 /* eXpress Transfer Protocol (no AF) */
#define AF_COIP 20 /* 面向连接的IP, 又名 ST II */
#define AF_CNT 21 /* Computer Network Technology */
#define pseudo_AF_RTIP 22 /* 用于识别RTIP包 */
#define AF_IPX 23 /* Novell 网间协议 */
#define AF_SIP 24 /* Simple 网间协议 */
#define pseudo_AF_PIP 25 /* 用于识别PIP包 */
#define AF_ISDN 26 /* 综合业务数字网(Integrated Services Digital Network) */
#define AF_E164 AF_ISDN /* CCITT E.164 推荐 */
#define pseudo_AF_KEY 27 /* 内部密钥管理功能 */
#define AF_INET6 28 /* IPv6 */
#define AF_NATM 29 /* 本征ATM访问 */
#define AF_ATM 30 /* ATM */
#define pseudo_AF_HDRCMPLT 31 /* 由BPF使用,就不必在接口输出例程
* 中重写头文件了
*/
#define AF_NETGRAPH 32 /* Netgraph 套接字 */
#define AF_SLOW 33 /* 802.3ad 慢速协议 */
#define AF_SCLUSTER 34 /* Sitara 集群协议 */
#define AF_ARP 35
#define AF_BLUETOOTH 36 /* 蓝牙套接字 */
#define AF_MAX 37
用于指定IP的是 AF_INET。这个符号对应着常量 2。
在sockaddr中的域 sa_family指定 地址族, 从而决定预先只确定下大致字节数的 sa_data的实际大小。
特别是当 地址族是AF_INET时,我们可以使用 struct sockaddr_in,这可在 netinet/in.h中找到,任何需要 sockaddr的地方都以此作为实际替代。
/*
* 套接字地址,Internet风格
*/
struct sockaddr_in {
u
7.5 重要的套接字函数
FreeBSD提供了与套接字相关的不同函数, “打开”一个套接字我们只 需要四个函数。 有时我们只需要两个。
7.5.1 客户端-服务器差异
典型情况中,以套接字为基础的数据通信一端是一个 服务器,另一端是一个 客户端。
7.5.1.1 通用元素
7.5.1.1.1 socket
这一个函数在客户端和服务器都要使用:socket(2)。它是这样被声明的:
int socket(int domain, int type, int protocol);
返回值的类型与open的相同,一个整数。 FreeBSD从和文件句柄相同的池中分配它的值。这就是允许套接字被以对文件相同的方式处理的原因。
参数domain告诉系统你需要使用什么 协议族。有许多种协议族存在,有些是某些厂商专有的,其它的都非常通用。协议族的声明在 sys/socket.h中
使用PF_INET是对于 UDP, TCP和其它网间协议(IPv4)的情况。
对于参数type有五个定义好的值,也在 sys/socket.h中。这些值都以 “SOCK_”开头。 其中最通用的是SOCK_STREAM, 它告诉系统你正需要一个 可靠的流传送服务(和PF_INET一起使用时是指 TCP)。
如果指定SOCK_DGRAM, 你是在请求 无连接报文传送服务(在我们的情形中是UDP)。
如何你需要处理基层协议 (例如IP),或者甚至是网络接口 (例如,以太网),你就需要指定 SOCK_RAW。
最后,参数protocol取决于前两个参数,并非总是有意义。在以上情形中,使用取值0。
未连接的套接字:对于函数socket我们还没有指定我们要连往什么其它(主机)系统。 我们新建的套接字还是 未连接的。
这是有意的:拿电话类比,我们刚把调制解调器接在电话线上。我们既没有告诉调制解调器发起一个呼叫,也不会应答电话振铃。
7.5.1.1.2 sockaddr
各种各样的套接字函数需要指定地址,那是一小块内存空间 (用C语言术语是指向一小块内存空间的指针)。在 sys/socket.h中有各种各样如 struct sockaddr的声明。 这个结构是这样被声明的:
/*
* 内核用来存储大多数种类地址的结构
*/
struct sockaddr {
unsigned char sa_len; /* 总长度 */
sa_family_t sa_family; /* 地址族 */
char sa_data[14]; /* 地址值,实际可能更长 */
};
#define SOCK_MAXADDRLEN 255 /* 可能的最长的地址长度 */
注意对于sa_data域的定义有些 不确定性。 那只是被定义为14字节的数组, 注释暗示内容可能超过14字节
这种不确定性是经过深思熟虑的。套接字是个非常强大的接口。多数人可能认为比Internet接口强不到哪里 ──大多数应用现在很可能都用它 ──套接字可被用于几乎 任何种类的进程间通信, Internet(更精确的说是IP)只是其中的一种。
sys/socket.h提到的各种类型的协议 将被按照 地址族对待,并把它们就列在 sockaddr定义的前面:
/*
* 地址族
*/
#define AF_UNSPEC 0 /* 未指定 */
#define AF_LOCAL 1 /* 本机 (管道,portal) */
#define AF_UNIX AF_LOCAL /* 为了向前兼容 */
#define AF_INET 2 /* 网间协议: UDP, TCP, 等等 */
#define AF_IMPLINK 3 /* arpanet imp 地址 */
#define AF_PUP 4 /* pup 协议: 例如BSP */
#define AF_CHAOS 5 /* MIT CHAOS 协议 */
#define AF_NS 6 /* 施乐(XEROX) NS 协议 */
#define AF_ISO 7 /* ISO 协议 */
#define AF_OSI AF_ISO
#define AF_ECMA 8 /* 欧洲计算机制造商协会 */
#define AF_DATAKIT 9 /* datakit 协议 */
#define AF_CCITT 10 /* CCITT 协议, X.25 等 */
#define AF_SNA 11 /* IBM SNA */
#define AF_DECnet 12 /* DECnet */
#define AF_DLI 13 /* DEC 直接数据链路接口 */
#define AF_LAT 14 /* LAT */
#define AF_HYLINK 15 /* NSC Hyperchannel */
#define AF_APPLETALK 16 /* Apple Talk */
#define AF_ROUTE 17 /* 内部路由协议 */
#define AF_LINK 18 /* 协路层接口 */
#define pseudo_AF_XTP 19 /* eXpress Transfer Protocol (no AF) */
#define AF_COIP 20 /* 面向连接的IP, 又名 ST II */
#define AF_CNT 21 /* Computer Network Technology */
#define pseudo_AF_RTIP 22 /* 用于识别RTIP包 */
#define AF_IPX 23 /* Novell 网间协议 */
#define AF_SIP 24 /* Simple 网间协议 */
#define pseudo_AF_PIP 25 /* 用于识别PIP包 */
#define AF_ISDN 26 /* 综合业务数字网(Integrated Services Digital Network) */
#define AF_E164 AF_ISDN /* CCITT E.164 推荐 */
#define pseudo_AF_KEY 27 /* 内部密钥管理功能 */
#define AF_INET6 28 /* IPv6 */
#define AF_NATM 29 /* 本征ATM访问 */
#define AF_ATM 30 /* ATM */
#define pseudo_AF_HDRCMPLT 31 /* 由BPF使用,就不必在接口输出例程
* 中重写头文件了
*/
#define AF_NETGRAPH 32 /* Netgraph 套接字 */
#define AF_SLOW 33 /* 802.3ad 慢速协议 */
#define AF_SCLUSTER 34 /* Sitara 集群协议 */
#define AF_ARP 35
#define AF_BLUETOOTH 36 /* 蓝牙套接字 */
#define AF_MAX 37
用于指定IP的是 AF_INET。这个符号对应着常量 2。
在sockaddr中的域 sa_family指定 地址族, 从而决定预先只确定下大致字节数的 sa_data的实际大小。
特别是当 地址族是AF_INET时,我们可以使用 struct sockaddr_in,这可在 netinet/in.h中找到,任何需要 sockaddr的地方都以此作为实际替代。
/*
* 套接字地址,Internet风格
*/
struct sockaddr_in {
u