Chinaunix首页 | 论坛 | 博客
  • 博客访问: 912551
  • 博文数量: 299
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2493
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-21 10:07
个人简介

Linux后台服务器编程。

文章分类

全部博文(299)

文章存档

2015年(2)

2014年(297)

分类: 网络与安全

2014-08-16 11:53:47

unix域套接字实际上不是一个实际的协议,他只是在同一台主机上客户和服务器之间通信时,使用与在不同主机上客户和服务器间通信时相同的API   

unix域套接字分为两种:字节流套接字和数据报套接字

unix域套接字的好处:

1 在同一台主机上进行通信时,是不同主机间通信的两倍

2 unix域套接口可以在同一台主机上,不同进程之间传递套接字描述符

3 unix域套接字可以向服务器提供客户的凭证(用户id或者用户组id)

unix域套接字使用的地址通常是文件系统中一个文件路径(套接口文件:APUE中的4.3节文件类型,是以s开头的),这些文件不是不同的文件,只能作为域套接字通信,不能读写


并且是以s开头的文件

unix域套接字的地址结构是:


  1. struct sockaddr_un  
  2. {  
  3.     uint8_t sun_len;  
  4.     sa_family_sun_family;//AF_LOCAL  
  5.     char sun_path[104];//必须是以空结尾的字符串(路径+文件名)  
  6. }  


int socketpair(int family, int type, intprotocol, int sockfd[2]);

这个函数创建两个互相连接的套接字(socketfd[2])family 是AF_LOCAL, type可以是SOCK_STREAM (字节流)或者SOCK_DGRAM(数据报),协议是0,之后就能够或者两个互相连接的套接字

以SOCK_STREAM调用的socketpair函数得到的套接字叫做流管道(stream pipe),是全双工的,就是这两个套接字是可读可写的

1在unix域套接字进行bind的时候建立套接口文件,其默认的权限值是0777,并被当前的umask修改,看上图就知道,umask是0022 的到的文件权限是0755

2关于bind创建文件中地址参数 sockaddr_un 中的sun_path需要是绝对路径,这样才能不用考虑相对的概念。防止客户端程序也用相对路径,但是和服务器不在同一个目录的考虑

3 connect中的地址中的路径名必须是套接口文件,而且已经被服务端绑定的,以下情况会出错:1 文件路径存在但是不是套接口文件2 路径名存在且是套接口文件,但是没有和该文件绑定的套接口3 就是type必须和服务器相同

4 connect连接unix套接口的时候的权限检查和open函数一样的

5 unix域字节流套接口和TCP一样都给进程提供一个无记录边界的字节流接口

6 unix域套接口connect发现等待队列满了,就直接返回ECONNREFUSRD错误,说连接拒绝错误

7 unix域数据报套接口和UDP一样提供一个保留记录边界的不可靠数据报服务

unix域套接字的客户端:


  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7.   
  8. #define MAX_SEND 1025  
  9. #define UNIX_PATH "/tmp/sinfor"  
  10.   
  11. void dump_unix(int sock_fd)  
  12. {  
  13.     char tmp[MAX_SEND] = {0};  
  14.     char recv[MAX_SEND] = {0};  
  15.     while(fgets(tmp, MAX_SEND, stdin) != NULL)  
  16.     {  
  17.         write(sock_fd, tmp, strlen(tmp));  
  18.         read(sock_fd, recv, MAX_SEND);  
  19.         printf("data : %s\n", recv);  
  20.         bzero(tmp,MAX_SEND);  
  21.         bzero(recv, MAX_SEND);  
  22.     }  
  23. }  
  24. int main(int argc, char** argv)  
  25. {  
  26.     int conn_sock = socket(AF_LOCAL, SOCK_STREAM, 0);  
  27.     if(conn_sock == -1)  
  28.     {  
  29.         perror("socket fail ");  
  30.         return -1;  
  31.     }  
  32.     struct sockaddr_un addr;  
  33.     bzero(&addr, sizeof(addr));  
  34.     addr.sun_family = AF_LOCAL;  
  35.     strcpy((void*)&addr.sun_path, UNIX_PATH);  
  36.     if(connect(conn_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)  
  37.     {  
  38.         perror("connect fail ");  
  39.         return -1;  
  40.     }  
  41.     dump_unix(conn_sock);  
  42.     close(conn_sock);  
  43.     return 0;  
  44. }  


unix域套接字的服务器;


  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7. #include   
  8. #include   
  9.   
  10. #define MAX_RECV 1025  
  11. #define UNIX_SERV_PATH "/tmp/sinfor"  
  12. void client_dump(int sock_fd)  
  13. {  
  14.     char rec[MAX_RECV] = {0};  
  15.     int size;  
  16.     while((size = read(sock_fd, rec, MAX_RECV)) != 0)  
  17.     {  
  18.         printf("**********1111************\n");  
  19.         printf("recv data is %s\n", rec);  
  20.         write(sock_fd, rec, size);  
  21.     }  
  22. }  
  23. void sig_son(int num)  
  24. {  
  25.     printf("son is %d\n", getpid());  
  26.     wait(NULL);  
  27.     //return NULL;  
  28. }  
  29. int main(int argc, char** argv)  
  30. {  
  31.     int acc_sock, dump_sock;  
  32.     acc_sock = socket(AF_LOCAL, SOCK_STREAM, 0);  
  33.     if(acc_sock == -1)  
  34.     {  
  35.         perror("socket func fail ");  
  36.         return -1;  
  37.     }  
  38.     struct sockaddr_un ser_addr, cli_addr;  
  39.     ser_addr.sun_family = AF_LOCAL;  
  40.     strcpy(ser_addr.sun_path, UNIX_SERV_PATH);  
  41.     unlink(UNIX_SERV_PATH);  
  42.     bind(acc_sock, (struct sockaddr*)&ser_addr, sizeof(ser_addr));  
  43.     listen(acc_sock, 5);  
  44.     signal(SIGCHLD, sig_son);  
  45.     while(1)  
  46.     {  
  47.         int len = sizeof(cli_addr);  
  48.         dump_sock = accept(acc_sock, (struct sockaddr*)&cli_addr, &len);  
  49.         if(dump_sock == -1)  
  50.         {  
  51.             if(errno == EINTR)  
  52.             {  
  53.                 continue;  
  54.             }  
  55.             else  
  56.             {  
  57.                 perror("accept fail");  
  58.                 return -1;  
  59.             }  
  60.         }  
  61.         if(fork() == 0)  
  62.         {  
  63.             close(acc_sock);  
  64.             client_dump(dump_sock);       
  65.             close(dump_sock);  
  66.             exit(0);  
  67.         }  
  68.         close(dump_sock);  
  69.     }  
  70.     close(acc_sock);  
  71.     return 0;  
  72. }  



这章还有用户认证和描述符通过unix套接字在不同进程之间传递,看完了,太累了,就不写了,有兴趣的自己看看unp吧
阅读(1300) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~