套接字的地址结构

来源:百度文库 编辑:神马文学网 时间:2024/10/04 15:20:02
套接字的地址格式有很多种,比如sockaddr、sockaddr_in、sockaddr_ipx、sockaddr_pkt、sockaddr_ll等等,这里就来谈谈他们的区别与联系。
struct sockaddr:
sockaddr是通用的socket地址,定义在“include/linux/socket.h“,其具体格式如下:
struct sockaddr {
sa_family_t sa_family;      /* address family, AF_xxx       */
char            sa_data[14];    /* 14 bytes of protocol address */
};
这里的family指的是协议族(或者说协议栈)。主要的协议族有以下:
PF_INET             互联网IPv4
PF_IPX                IPX协议
PF_NETLINK     一个用户空间和内核的接口
PF_PACKET       底层数据包接口
所有这些地址格式都对应着不同的网络协议。这里sockaddr_xxx中的xxx即表明了其所用的网络协议。比如,互联网的socket结构使用struct sockaddr_in,可以与sockaddr进行类型转换。
struct sockaddr_in:
该结构定义在”include/linux/in.h“
struct sockaddr_in {
sa_family_t sin_family;     /* Address family               */
__be16 sin_port;       /* Port number                  */
struct in_addr sin_addr;       /* Internet address             */
/* Pad to size of `struct sockaddr’. */
unsigned char         __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
这里可以看到,之所以可以进行类型转换,是因为在定义sockaddr_in的时候就通过补齐的方法使二者大小一致(并不是所有的sockaddr_xxx都如此)。
/* Internet address. */
struct in_addr {
__be32 s_addr;
};
这个in_addr即是32位的IP地址,在有的版本中也定义为:
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4;} S_un_b;
struct { u_short s_w1,s_w2;} S_un_w;
u_long S_addr;
} S_un;
};
利用u_long htonl(u_long hostlong);将主机字节序转换为TCP/IP网络字节序.
利用u_short htons(u_short hostshort);将主机字节序转换为TCP/IP网络字节序.
inet_addr()是将一个点分制的IP地址(如192.168.0.1)转换为上述结构中需要的32位IP地址(0xC0A80001)。
以一个典型的互联网套接字程序来说明用法:
int sockfd;
struct sockaddr_in my_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0); /* 做一些错误检查! */
my_addr.sin_family = AF_INET; /* 主机字节序 */
my_addr.sin_port = htons(MYPORT); /* short, 网络字节序 */
my_addr.sin_addr.s_addr = inet_addr(“192.168.0.1″);
bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */
/* 不要忘了为bind()做错误检查: */
bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
想来你是要进行网络编程,使用socket, listen, bind等函数。你只要记住,填值的时候使用sockaddr_in结构,而作为函数的参数传入的时候转换成sockaddr结构就行了,毕竟都是16个字符长。
struct sockaddr_ll
这是一个与设备无关的物理层地址格式,需要使用AF_PACKET协议族,适合用来实现用户态下的网络协议栈。
struct sockaddr_ll
{
unsigned short sll_family;   /* Always AF_PACKET */
unsigned short sll_protocol; /* Physical layer protocol */
int            sll_ifindex;  /* Interface number */
unsigned short sll_hatype;   /* Header type */
unsigned char  sll_pkttype;  /* Packet type */
unsigned char  sll_halen;    /* Length of address */
unsigned char  sll_addr[8];  /* Physical layer address */
};
----------------------
References:
Linux Kernel Version 2.6.22
http://blog.csdn.net/zysee/archive/2007/01/16/1484235.aspx
===============补充=================
以太网头部结构,一共14个字节:
104 struct ethhdr {
105 unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
106 unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
107 __be16 h_proto;                /* packet type ID field */
108 } __attribute__((packed));
ETH_ALEN被定义为6,即以太网MAC地址的长度。h_proto在I386和arm上都是unsigned long类型,它用来保存type的值。type是接口的硬件类型,以太网设备的初始化函数中将其赋值为ARPHRD_ETHER,即10Mb以太网。具体的类型定义在/usr/include/linux/if_arp.h中。如有需要,可以考虑定义自己的网络类型(比如ARPHDR_AQUANET之类的)。
(Kernel Version 2.6.18)
===============补充2=================
UNIX套接字 sockaddr_un
这是和AF_LOCAL搭配使用创建本地套接字的,是一种进行本地进程间IPC的方法。
/* Structure describing the address of an AF_LOCAL (aka AF_UNIX) socket. */struct sockaddr_un { __SOCKADDR_COMMON (sun_); char sun_path[108]; /* Path name. */ };
注意,在调用connect/bind/accept时,要强制类型转换为(struct sockadd *)格式,否则编译时会报告指针类型错误,比如:
warning: passing argument 2 of connect from incompatible pointer typewarning: passing argument 2 of bind from incompatible pointer typewarning: passing argument 2 of accept from incompatible pointer type
(Visited 491 times, 3 visits today)
November 8th, 2007 | Category: Programming, Technique | Leave a comment |