zoukankan      html  css  js  c++  java
  • nginx源码学习Unix Unix域协议

      说到什么是域协议就会出现这么个解释:

      UNIX域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务器通信的一种方法,所用API与在不同主机上执行客户/服务器通信所使用的API相同。UNIX域协议可以视为IPC方法之一。

      我们白话解释下Unix域协议在什么情况下使用和怎么使用?

      Unix域协议主要用在同一台机子的不同进程之间传递套接字。为什么不用TCP或者UDP套接字呢?一是因为快。源自Berkeley的实现中,Unix域套接字往往比通信两端位于同一个主机的TCP套接字快出一倍。二是因为安全。Unix套接字能提供额外的安全检查措施。

      注意:Unix域协议表示协议地址的是路径名,而不是Inet域的IP地址和端口号

      socket地址结构:

      #include<sys/un.h>
      struct sockaddr_un {
      	sa_family_t sun_family; /*AF_LOCAL*/
      	char sun_path[104];     /*null-terminated pathname*/
      };

      至于他们的程序和TCPsocket没有什么区别

      服务器端:

      Unix_Domain_ser.c                                                                                                                                                                            
      
      #include <stdio.h>
      #include <sys/types.h>
      #include <sys/socket.h>
      #include <netinet/in.h>
      #include <string.h>
      #include <unistd.h>
      #include <sys/un.h>
      #include <sys/select.h>
      
      int main(int argc, char *argv[])
      {
          int listenfd1;
          struct sockaddr_un serv_addr1;
          //这里使用的AF_LOCAL代表是Unix域协议
          listenfd1 = socket(AF_LOCAL, SOCK_STREAM, 0); 
          
          bzero(&serv_addr1, sizeof(struct sockaddr_un));
          serv_addr1.sun_family = AF_LOCAL;
          strncpy(serv_addr1.sun_path, argv[1], sizeof(serv_addr1.sun_path)-1);
      
          bind(listenfd1, (struct sockaddr *)&serv_addr1, SUN_LEN(&serv_addr1));
          listen(listenfd1, 5); 
         
          int clifd; 
          char buffer[256];
          //如果是listenfd1 获取消息
          clifd = accept(listenfd1, NULL, NULL);
          
          bzero(buffer, 256);
          read(clifd, buffer, 255);
          printf("Listenfd1 Message is:%s\r\n", buffer);
          
          close(listenfd1);
          return 0;
      
      }

      客户端:

      Unix_Domain_cli.c                                                                                                                                                                            
      
      #include <stdio.h>
      #include <sys/socket.h>
      #include <sys/types.h>
      #include <netinet/in.h>
      #include <string.h>
      #include <unistd.h>
      #include <sys/un.h>
      
      int main(int argc, char* argv[])
      {
          int socketfd, n;
          socketfd = socket(AF_LOCAL, SOCK_STREAM, 0); 
          
          struct sockaddr_un serv_addr;
          
          bzero((char *)&serv_addr, sizeof(serv_addr));
          serv_addr.sun_family = AF_LOCAL;
          strncpy(serv_addr.sun_path, argv[1], sizeof(struct sockaddr_un));
          
          connect(socketfd,(struct sockaddr *)  &serv_addr, SUN_LEN(&serv_addr));
          
          write(socketfd, "client message", 14);
          return 0;
      
      }

      服务端命令:

      clip_image001

      客户端命令:

      clip_image002

      参考文档:

      http://memorymyann.iteye.com/blog/649619

      http://hi.baidu.com/wangjianzhong1981/blog/item/d91d1c1073b2e409203f2e4d.html

      socketpair函数

      #include <sys/socket.h>

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

      1 socketpair创建两个socket,并连接起来,只用于Unix域

      2 family参数必须为AF_LOCAL,protocol参数必须为0,

      socketpair函数主要用在什么地方呢?当父进程fork出一个子进程的时候,两个进程需要使用Unix套接字进行进程间通信,那么socketpair就可以使用到了

      发现说什么还是不如写代码实在:

      Unix_Domain_Sockpair.c                                                                                                                                                                       
      
      #include <stdio.h>
      #include <sys/types.h>
      #include <sys/socket.h>
      #include <netinet/in.h>
      #include <string.h>
      #include <unistd.h>
      #include <sys/un.h>
      
      int main(int argc, char *argv[])
      {
          int sockets[2];
          char buffer[1024];
      
          socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets);
      
          int child;
          child = fork();
          if(child) { //父进程
              close(sockets[0]);
              read(sockets[1], buffer, 255);
              printf("parent read--> %s\r\n", buffer);
              close(sockets[1]);
          } else {  //子进程
              close(sockets[1]);
              write(sockets[0], "Message", sizeof("Message"));
              printf("child write--> Message\r\n");
              close(sockets[0]);
          }   
          return 0;
      
      }

      执行程序:

      clip_image003

      nginx中的socketpair使用:

      在nginx_process.c中你会看到这个:

      clip_image004

      这里得到几个信息:

      1 Solaris 9 没有AF_LOCAL这个属性,所以使用AF_UNIX属性来代替

      2 nginx每个worker进程之间都有channel通道,通道就是使用socketpair创建的

      参考文档:

      http://osr507doc.sco.com/en/netguide/dusockD.socketpairs_codetext.html

    实时了解作者更多技术文章,技术心得,请关注微信公众号“轩脉刃的刀光剑影”

    本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名叶剑峰(包含链接http://www.cnblogs.com/yjf512/),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系

  • 相关阅读:
    怎样使用七牛云CDN加速并绑定阿里云域名
    mac系统Docker安装Redis教程
    使用Java Executor框架实现多线程
    我是怎样测试Java类的线程安全性的
    Java8 Stream终端操作使用详解
    Java8 Stream中间操作使用详解
    Java 8创建Stream流的5种方法
    JVM源码分析之Metaspace解密
    全链路压测体系建设方案的思考与实践
    JVM源码分析之Object.wait/notify(All)完全解读
  • 原文地址:https://www.cnblogs.com/yjf512/p/2541401.html
Copyright © 2011-2022 走看看