《UNIX环境高级编程》笔记--UNIX域套接字

来源:互联网 发布:数据库酒店管理系统 编辑:程序博客网 时间:2024/06/04 19:20

1.非命名的UNIX域套接字

UNIX套接字用于在用一台机器上运行的进程之间通信。UNIX套接字比因特网域套接字的效率更高。UNIX与套接字提供和

数据报两种接口,UNIX域数据报服务是可靠的,就不会丢失消息也不会传递出错。UNIX域套接字是套接字和管道之间的混合物。

为了创建一对非命名的,相互连接的UNXI域套接字,用户可以使用socketopair函数。

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include<sys/socket.h>  
  2. int socketpari(int domain, int type, int protocol, int sockfd[2]); //若成功则返回0,出错则返回-1.  
实践:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <sys/socket.h>  
  4. #include <string.h>  
  5.   
  6. int main(void){  
  7.         int fd[2];  
  8.         int pid;  
  9.         char wbuf[16] = "1234567890";  
  10.         char rbuf[16];  
  11.         if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0){  
  12.                 perror("socketpair");  
  13.                 return -1;  
  14.         }  
  15.   
  16.         if((pid = fork())<0){  
  17.                 perror("fork");  
  18.                 return -1;  
  19.         }else if(pid == 0){  
  20.                 //child  
  21.                 close(fd[0]);  
  22.                 if(write(fd[1],wbuf,strlen(wbuf)) < 0){  
  23.                         perror("write");  
  24.                         exit(-1);  
  25.                 }  
  26.         }else{  
  27.                 //parent  
  28.                 close(fd[1]);  
  29.                 if(read(fd[0],rbuf,16) < 0){  
  30.                         perror("read");  
  31.                         exit(-1);  
  32.                 }  
  33.                 printf("%s\n",rbuf);  
  34.         }  
  35.         return 0;  
  36. }  
执行结果:

yan@yan-vm:~$ ./a.out
1234567890


2.命名UNIX域套接字

虽然socketpair函数创建相互连接的一对套接字,但是每一个套接字都没有名字。这意味着无关进程不能使用它们。

我们可以命名unix域套接字,并可将其用于告示服务。但是要注意的是,UNXI与套接字使用的地址不同与因特网域套接字。

UNIX域套接字的地址由sockaddr_un结构表示。

在linux2.4.22中,sockaddr_un结构按下列形式定义在有文件<sys/un.h>中。

struct sockaddr_un{

sa_family_t sun_family; //AF_UNIX

char sun_path[108]; //pathname

};

sun_path成员包含一路经名,当我们将一个地址绑定至UNIX域套接字时,系统用该路经名创建一类型为S_IFSOCK文件。

该文件仅用于向客户进程告知套接字名字。该文件不能打开,也不能由应用程序用于通信。

如果当我们试图绑定地址时,该文件已经存在,那么bind请求失败。当关闭套接字时,并不自动删除该文件,所以我们必须

确保在应用程序终止前,对该文件执行解除链接操作。

服务器进程可以使用标准bind、listen和accept函数,为客户进程安排一个唯一UNIX域连接。客户进程使用connect与服务器

进程连接;服务器进程接受了connect请求后,在服务器进程和客户进程之间就存在了唯一连接。这种风格和因特网套接字

的操作很像。

实践:

server.c

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <sys/socket.h>  
  3. #include <sys/un.h>  
  4. #include <string.h>  
  5.   
  6. int main(void){  
  7.         int fd,clientfd;  
  8.         int client_addr_len = sizeof(struct sockaddr_un);  
  9.         struct sockaddr_un un,clientun;  
  10.         char path[32]="serversocketfile";  
  11.         int addr_len = sizeof(struct sockaddr_un);  
  12.         char rbuf[32];  
  13.         char wbuf[32] = "i am server.";  
  14.   
  15.         //create a UNIX domain stream socket  
  16.         if((fd = socket(AF_UNIX,SOCK_STREAM,0)) < 0){  
  17.                 perror("socket");  
  18.                 return -1;  
  19.         }  
  20.   
  21.         //in case it already exists  
  22.         unlink(path);  
  23.   
  24.         //fill in socket address structure  
  25.         memset(&un, 0, sizeof(un));  
  26.         un.sun_family = AF_UNIX;  
  27.         strncpy(un.sun_path,path,32);  
  28.   
  29.         //bind the name to the descriptor  
  30.         if(bind(fd, (struct sockaddr*)&un, addr_len) < 0){  
  31.                 perror("bind");  
  32.                 return -1;  
  33.         }  
  34.   
  35.         if(listen(fd, 10) < 0){  
  36.                 perror("listen");  
  37.                 return -1;  
  38.         }  
  39.   
  40.         if((clientfd = accept(fd,(struct sockaddr*)&clientun,(socklen_t*)&client_addr_len)) < 0 ){  
  41.                 perror("accept");  
  42.                 return -1;  
  43.         }  
  44.   
  45.         printf("client is:%s\n",clientun.sun_path);  
  46.   
  47.         if(read(clientfd,rbuf,32) < 0){  
  48.                 perror("read");  
  49.                 return -1;  
  50.         }  
  51.         printf("receive msg:%s\n",rbuf);  
  52.   
  53.         if(write(clientfd,wbuf,strlen(wbuf)+1) < 0){  
  54.                 perror("write");  
  55.                 return -1;  
  56.         }  
  57.   
  58.         unlink(path);  
  59.         return 0;  
  60. }  

client.c

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <sys/un.h>  
  3. #include <sys/socket.h>  
  4. #include <string.h>  
  5.   
  6. int main(void){  
  7.         int fd;  
  8.         struct sockaddr_un un;  
  9.         char path[32] = "clientsocketfile";  
  10.         char serverpath[32] = "serversocketfile";  
  11.         int addr_len = sizeof(struct sockaddr_un);  
  12.         char wbuf[32] = "i am client.";  
  13.         char rbuf[32];  
  14.   
  15.         if((fd = socket(AF_UNIX,SOCK_STREAM,0))<0){  
  16.                 perror("socket");  
  17.                 return -1;  
  18.         }  
  19.   
  20.         memset(&un,0,sizeof(un));  
  21.         un.sun_family = AF_UNIX;  
  22.         strncpy(un.sun_path,path,32);  
  23.         unlink(path);  
  24.   
  25.         if(bind(fd,(struct sockaddr*)&un,addr_len)<0){  
  26.                 perror("bind");  
  27.                 return -1;  
  28.         }  
  29.   
  30.         //fill socket adress structure with server's address  
  31.         memset(&un,0,sizeof(un));  
  32.         un.sun_family = AF_UNIX;  
  33.         strncpy(un.sun_path,serverpath,32);  
  34.   
  35.         if(connect(fd,(struct sockaddr*)&un,addr_len) < 0){  
  36.                 perror("connect");  
  37.                 return -1;  
  38.         }  
  39.   
  40.         if(write(fd,wbuf,strlen(wbuf)+1)<0){  
  41.                 perror("write");  
  42.                 return -1;  
  43.         }  
  44.   
  45.         if(read(fd,rbuf,32) < 0){  
  46.                 perror("write");  
  47.                 return -1;  
  48.         }  
  49.         printf("receive msg:%s\n",rbuf);  
  50.         unlink(path);  
  51.         return -1;  
  52. }  

先运行server,再运行client。

运行结果:

server.c:

yan@yan-vm:~/apue$ ./unixserver
client is:clientsocketfile
receive msg:i am client.

client.c:

yan@yan-vm:~/apue$ ./unixclient
receive msg:i am server.


0 0
原创粉丝点击