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字符串,主要用在采用数据包协议时需要获取对端地址的情况

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

  • 相关阅读:
    linux内核编译步骤
    Linux strace命令
    通过Wifi调试Android应用
    [Java 7][msvcr100.dll] Error when load Eclipse
    Cobar 关系型数据的分布式处理系统
    升级SUSE Linux内核的完整步骤!
    Qt 5.7 亮瞎眼的更新
    QT5.11下载与安装教程
    Delphi 对象模型学习笔记(转)
    内存共享【Delphi版】
  • 原文地址:https://www.cnblogs.com/skyofbitbit/p/3672888.html
Copyright © 2011-2022 走看看