zoukankan      html  css  js  c++  java
  • 转:sock_ev——linux平台socket事件框架(uri地址的解析) .

    在第一篇中,已经说明,传递的socket地址采取以下形式:

    [cpp] view plaincopyprint?
    stream://192.168.2.10:8080  
    dgram://192.168.2.10:8080  
    stream://unix.domain.ipc  
    dgram://unix.domain.ipc 
    stream://192.168.2.10:8080
    dgram://192.168.2.10:8080
    stream://unix.domain.ipc
    dgram://unix.domain.ipc今天看一下这个uri地址的解析过程,是如何转化成socket地址的,废话不多说,直接上代码

     
    /***************************************************************************************
    ****************************************************************************************
    * FILE      : socket_addr.h
    * Description   : 
    *             
    * Copyright (c) 2012 by Liu Yanyun(E-mail:liuyun827@foxmail.com). All Rights Reserved.
    *            Without permission, shall not be used for any commercial purpose

    * History:
    * Version       Name            Date            Description
       0.1      Liu Yanyun      2012/12/05      Initial Version
       
    ****************************************************************************************
    ****************************************************************************************/ 
     
     
    #ifndef _SOCKET_ADDR_H_  
    #define _SOCKET_ADDR_H_  
     
    #include <stdio.h>  
    #include <string.h>  
    #include <stdint.h>  
    #include <unistd.h>  
    #include <stdlib.h>  
    #include <sys/socket.h>  
    #include <stddef.h>  
    #include <sys/un.h>  
    #include <netinet/in.h>  
    #include <sys/types.h>  
    #include <arpa/inet.h>  
    #include <string>  
    #include <iostream>  
     
     
    /*==================================================================
    * class : SockAddr
    * Description   : parse uri address and serialize to string
    ==================================================================*/ 
    class SockAddr 

    public: 
     
      /*==================================================================
      * Function    : SockAddr.SockAddr
      * Description : construction function
      * Input Para  : uri address sting
      * Output Para : null
      * Return Value: 
      ==================================================================*/ 
      SockAddr(std::string uri_); 
     
      /*==================================================================
      * Function    : SockAddr.SockAddr
      * Description : construction function
      * Input Para  : domain_ -- address family
      * Input Para  : type_ -- specifies the communication semantics
      * Output Para : null
      * Return Value: 
      ==================================================================*/ 
      SockAddr(int domain_, int type_); 
     
      /*==================================================================
      * Function    : SockAddr.~SockAddr
      * Description : Destructor function
      * Input Para  : 
      * Output Para : 
      * Return Value: 
      ==================================================================*/ 
      virtual ~SockAddr(); 
     
      /*==================================================================
      * Function    : SockAddr.parseUri
      * Description : parse uri to socket address
      * Input Para  : void
      * Output Para : 
      * Return Value: if success return true,or else false return
      ==================================================================*/ 
      bool parseUri(); 
     
      /*==================================================================
      * Function    : SockAddr.toStr
      * Description : convert socket address to uri
      * Input Para  : store uri buf
      * Output Para : uri string
      * Return Value: if success return true,or else false return
      ==================================================================*/ 
      bool toStr(std::string &str_); 
     
      /*==================================================================
      * Function    : SockAddr.getDomain
      * Description : get socket domain
      * Input Para  : void
      * Output Para : 
      * Return Value: address famliy
      ==================================================================*/ 
      int getDomain(); 
     
      /*==================================================================
      * Function    : SockAddr.getType
      * Description : get communication type
      * Input Para  : void
      * Output Para : 
      * Return Value: communication type
      ==================================================================*/ 
      int getType(); 
     
      /*==================================================================
      * Function    : SockAddr.getSockLen
      * Description : get socket addrss length
      * Input Para  : void
      * Output Para : 
      * Return Value: socket addrss length
      ==================================================================*/ 
      socklen_t getSockLen(); 
     
      /*==================================================================
      * Function    : SockAddr.getAddr
      * Description : get socket addrss
      * Input Para  : void
      * Output Para : 
      * Return Value: socket addrss pointer
      ==================================================================*/ 
      struct sockaddr* getAddr(); 
     
    private: 
     
      static const int unixMaxPath = 108 - 1; 
      //AF_INET; AF_UNIX  
      int domain; 
     
      //SOCK_STREAM; SOCK_DGRAM  
      int type; 
      union 
      { 
        struct sockaddr_in inetAddr; 
        struct sockaddr_un unixAddr; 
      }; 
     
      std::string uri; 
    }; 
     
    #endif /*_SOCKET_ADDR_H_*/ 

    目前不支持ipv6协议,从上面的union可以看出;

    L127:静态常量unixMaxPath是unix域套接字中使用的,表示路径的最大长度-1;


    /***************************************************************************************
    ****************************************************************************************
    * FILE      : socket_addr.cc
    * Description   : 
    *             
    * Copyright (c) 2012 by Liu Yanyun(E-mail:liuyun827@foxmail.com). All Rights Reserved.
    *            Without permission, shall not be used for any commercial purpose

    * History:
    * Version       Name            Date            Description
       0.1      Liu Yanyun      2012/12/05      Initial Version
       
    ****************************************************************************************
    ****************************************************************************************/ 
     
     
    #include "log_trace.h"  
    #include "socket_addr.h"  
     
    using namespace std; 
     
    SockAddr::SockAddr(std::string uri_) 

      uri = uri_; 
      domain = 0; 
      type = 0; 
      memset(&unixAddr, 0, sizeof(unixAddr)); 

    SockAddr::SockAddr(int domain_, int type_) 

      domain = domain_; 
      type = type_; 
      memset(&unixAddr, 0, sizeof(unixAddr)); 

     
    SockAddr::~SockAddr() 

      //do nothing  

     
    struct sockaddr* SockAddr::getAddr() 

      if(AF_INET == domain) 
      { 
        return (struct sockaddr*)&inetAddr; 
      } 
      else if(AF_UNIX == domain) 
      { 
        return (struct sockaddr*)&unixAddr; 
      } 
      else 
      { 
        logTrace("invalid sockct domain:%d", domain); 
        return NULL; 
      } 

    int SockAddr::getDomain() 

      return domain; 

    int SockAddr::getType() 

      return type; 

     
    socklen_t SockAddr::getSockLen() 

      if(AF_INET == domain) 
      { 
        return sizeof(inetAddr); 
      } 
      else if(AF_UNIX == domain) 
      { 
        return sizeof(unixAddr); 
      } 
      else 
      { 
        logTrace("invalid sockct domain:%d", domain); 
        return 0; 
      } 

     
     
    /*
    "stream://127.0.0.1:8888"
    "dgram://127.0.0.1:8888"
    "stream://string"
    "dgram://string"
    */ 
    bool SockAddr::parseUri() 

      string::size_type pos = uri.find ("://"); 
      if(string::npos == pos)  
      { 
        logTrace("invalid uri:%s", uri.c_str()); 
        return false; 
      } 
       
      string protocol = uri.substr (0, pos); 
      string addrStr = uri.substr (pos + 3); 
      if(protocol.empty () || addrStr.empty ())  
      { 
        logTrace("invalid uri:%s", uri.c_str()); 
        return false; 
      } 
     
      if("stream" == protocol) 
      { 
        type = SOCK_STREAM; 
      } 
      else if("dgram" == protocol) 
      { 
        type = SOCK_DGRAM; 
      } 
      else 
      { 
        logTrace("invalid uri:%s", uri.c_str()); 
        return false; 
      } 
     
      pos = addrStr.find (":"); 
      if(string::npos == pos)  
      { 
        domain = AF_UNIX; 
        unixAddr.sun_family = AF_UNIX; 
        snprintf(&unixAddr.sun_path[1], unixMaxPath, "%s", addrStr.c_str()); 
        return true; 
      } 
      else 
      { 
        domain = AF_INET; 
        inetAddr.sin_family = AF_INET; 
        string ip = addrStr.substr (0, pos); 
        string port = addrStr.substr (pos + 1); 
        if(ip.empty () || port.empty ())  
        { 
          logTrace("invalid uri:%s", uri.c_str()); 
          return false; 
        } 
     
        inetAddr.sin_port = htons(atoi(port.c_str())); 
        if("*" == ip) 
        { 
          inetAddr.sin_addr.s_addr = htonl (INADDR_ANY); 
        } 
        else 
        { 
          int rc = inet_pton(AF_INET, ip.c_str(), &inetAddr.sin_addr); 
          if(rc <= 0) 
          { 
            logTrace("invalid uri:%s;%m", uri.c_str()); 
            return false; 
          } 
        } 
     
        return true; 
      } 

     
    bool SockAddr::toStr(string &str_) 

      if("" != uri) 
      { 
        str_ = uri; 
        return true; 
      } 
       
      if(AF_INET == domain) 
      { 
        char ipStr[INET_ADDRSTRLEN] = {0}; 
        if(NULL == inet_ntop(AF_INET, &inetAddr.sin_addr, ipStr, INET_ADDRSTRLEN)) 
        { 
          logTrace("invalid sin_addr;%m"); 
          return false; 
        } 
     
        char tmp[256] = {0}; 
        if(SOCK_STREAM == type) 
        { 
          snprintf(tmp, sizeof(tmp), "stream://%s:%d", ipStr, ntohs(inetAddr.sin_port)); 
        } 
        else if(SOCK_DGRAM == type) 
        { 
          snprintf(tmp, sizeof(tmp), "dgram://%s:%d", ipStr, ntohs(inetAddr.sin_port)); 
        } 
        else 
        { 
          logTrace("invalid type:%d", type); 
          return false; 
        } 
         
        str_ = tmp; 
        uri = tmp; 
     
        return true; 
      } 
      else if(AF_UNIX == domain) 
      { 
        char tmp[256] = {0}; 
        if(SOCK_STREAM == type) 
        { 
          snprintf(tmp, sizeof(tmp), "stream://%s", &unixAddr.sun_path[1]); 
        } 
        else if(SOCK_DGRAM == type) 
        { 
          snprintf(tmp, sizeof(tmp), "dgram://%s", &unixAddr.sun_path[1]); 
        } 
        else 
        { 
          logTrace("invalid type:%d", type); 
          return false; 
        } 
     
        str_ = tmp; 
        uri = tmp; 
     
        return true; 
      } 
      else 
      { 
        logTrace("invalid sockct domain:%d", domain); 
        return false; 
      } 

    L41:返回的socket地址是根据domain判定的

    L92:首先查找'://'前面的字串表示使用的是字节流协议还是数据包协议

    L121:在从剩余子串中查找':',找到标识采用的是ip:port形式,即使用的是inet域协议,找不到认为是unix域协议

    L142:对server端ip为'*',表示绑定到任意网卡

    L160:返回socket地址对应的uri字符串,主要用在采用数据包协议时需要获取对端地址的情况

    上面的这个类对于使用者是不可见的,属于内部使用类。

  • 相关阅读:
    使用golang访问kubebernetes
    使用 Rancher 管理现有 Kubernetes 集群
    Running powershell scripts during nuget package installation and removal
    How to Create, Use, and Debug .NET application Crash Dumps in 2019
    寻找写代码感觉(一)之使用 Spring Boot 快速搭建项目
    Selenium+Java之解决org.openqa.selenium.InvalidArgumentException: invalid argument报错问题
    Selenium环境搭建
    关于Xpath定位方法知道这些基本够用
    Web自动化之浏览器启动
    【翻译】编写代码注释的最佳实践
  • 原文地址:https://www.cnblogs.com/skyofbitbit/p/3672888.html
Copyright © 2011-2022 走看看