格式化抽象本地地址
传统AF_UNIX套接口名字的麻烦之一就在于总是调用文件系统对象。这不是必须的,而且也不方便。如果原始的文件系统对象并没有删除,而在bind调用时使用相同的文件名,名字赋值就会失败。
Linux 2.2内核使得为本地套接口创建一个抽象名了成为可能。他的方法就是使得路径名的第一个字节为一个空字节。在路径名中空字节之后的字节才会成为抽象名字的一部分。下面的这个程序是上一个例子程序的修改版本。这个程序采用了一些不同的方法来创建一个抽象的名字。
/*****************************************
* af_unix2.c
*
* AF_UNIXSocket Example
* CreateAbstract Named AF_UNIX/AF_LOCAL
*******************************************/
#include<stdio.h>
#include<stdlib.h>
#include<error.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/stat.h>
#include<sys/un.h>
/*
* Thisfunction reports the error and
* exits backto the shell:
*/
static voidbail(const char *on_what)
{
perror(on_what);
exit(1);
}
int main(intargc,char **argv,char **envp)
{
int z; /* Status return code */
int sck_unix; /* Socket */
struct sockaddr_un adr_unix; /* AF_UNIX */
int len_unix; /* length */
const char pth_unix[] /* Abs .Name */
= "Z*MY-SOCKET*";
/*
* Create an AF_UNIX (aka AF_UNIX) socket:
*/
sck_unix = socket(AF_UNIX,SOCK_STREAM,0);
if(sck_unix == -1)
bail("socket()");
/*
* Form an AF_UNIX Address
*/
memset(&adr_unix,0,sizeof adr_unix);
adr_unix.sun_family = AF_UNIX;
strncpy(adr_unix.sun_path,pth_unix,
sizeof adr_unix.sun_path-1)
[sizeof adr_unix.sun_path-1] = 0;
len_unix = SUN_LEN(&adr_unix);
/*
* Now make first byte null
*/
adr_unix.sun_path[0] = 0;
z = bind(sck_unix,(struct sockaddr *)&adr_unix,len_unix);
if(z == -1)
bail("bind()");
/*
* Display all of our bound sockets:
*/
system("netstat -pa --unix 2>/dev/null |"
"sed -n '/^Active UNIX/,/^Proto/P;"
"/af_unix/P'");
/*
* Close and unlink our socket path:
*/
close(sck_unix);
return 0;
/*
* Now bind the address to the socket:
*/
}
这个程序的运行结果如下:
$ ./af_unix2
Active UNIX domainsockets (servers and established)
Proto RefCntFlags Type State I-Node PID/Programname Path
unix0 [] STREAM 1041435186/af_unix2 @*MY- SOCKET*
$
从这个输出结果中我们可以看到,套接口地址是以 @*MYSOCKET*的名字出现的。开头的@标志是为netstat命令用来标识抽象UNIX套接口名字。其余的字符是拷贝到字符数组剩余位置的字符。注意@字符出现在我们的Z字符应出现的地方。
整个程序的步骤与前一个程序的相同。然而,地址的初始化步骤有一些不同。这些步骤描述如下:
1 在第31行和第32行定义了套接口抽象名字的字符串。注意字符串的第一个字符为Z。在这个字符串这个多余的字符只是起到占位的作用,因为实际上他会在第6步被一个空字节代替。
2 在第45行通过调用memset函数将整个结构初始经为0。
3 在第47行将地址族设置为AF_UNIX。
4 在第49行使用strncpy函数将抽象名字拷贝到adr_unix.sun_path中。在这里要注意,为了SUN_LEN()宏的使用在目的字符数组的放置了一个结束的空字节。否则就不需要这个结束的空字节。
5 在第53通过Linux所提供的SUN_LEN() C 宏来计算地址的长度。这个宏会在sun_path[]上调用strlen函数,所以需要提供了一个结束字符。
6 这一步是新的:sun_path[]数组的第一个字节被设置为空字节。如果使用SUN_LEN()宏,必须最后执行这一步。
在这一部分,我们了解了如何来创建AF_LOCAL和AF_UNIX的套接口地址。为了计算套接口地址的长度,我们使用SUN_LEN()宏。然而,当计算抽象套接口名字时,我们要十分注意。