在第一篇中,已经说明,传递的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字符串,主要用在采用数据包协议时需要获取对端地址的情况

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

转:sock_ev——linux平台socket事件框架(uri地址的解析) .的更多相关文章

  1. 转:sock_ev——linux平台socket事件框架(event loop) .

    上一篇我们封装了三种事件监听方式,如果分别提供给客户端使用,有点不方便,也不利于统一管理:我们再封装一层EventLoop. /************************************ ...

  2. 转:sock_ev——linux平台socket事件框架(socket API的封装) .

    把linux平台提供的有关socket操作的API进行封装是有必要的:基于stream操作的流程与基于dgram操作的流程略有不同,分别放在两个类中,但两者又有很多相似的操作,因此写一个基类,让其继承 ...

  3. 转:sock_ev——linux平台socket事件框架(event dispatcher) .

    最近比较忙,好久没更新了:今天我们看一下事件的监听方式,在linux下面事件的监听方式有三种select.poll.epoll,性能上面epoll最高,如果仅是最多监听十多个描述符,用啥无所谓,如果是 ...

  4. 转:sock_ev——linux平台socket事件框架(基于字节流的测试程序) .

    原文:http://blog.csdn.net/gdutliuyun827/article/details/8257186 由于工作与学习的需要,写了一个socket的事件处理框架,在公司写的已经使用 ...

  5. 转:sock_ev——linux平台socket事件框架(socket代理类) .

    前面分析了对socket基本操作的封装,并按照数据的传送方式写了两个类,本篇将写一个代理类提供给库的使用者使用的类. /**************************************** ...

  6. 转:sock_ev——linux平台socket事件框架(基于数据报的测试程序) .

    上一篇已经做过注释,这一篇直接上代码 /******************************************************************************** ...

  7. 转:sock_ev——linux平台socket事件框架(logTrace) .

    写代码要有调试log,采用syslog的输出:一般会输出到"/var/log/messages" /**************************************** ...

  8. linux下内存大小、起始地址的解析与修改

    在实际的工作中,由于产品型号的不同,经常需要调整linux所管理的内存的大小,而内核在启动阶段,会两次去解析从uboot传递过来的关于内存的信息,具体如下: 一.解析从uboot传递过来的tag(在p ...

  9. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

随机推荐

  1. Java高级架构师(一)第41节:Nginx的配置优化以及使用建议

  2. Nginx服务器的启动控制

    写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------主要内容包括: nginx服 ...

  3. 51nod 1010 只包含因子2 3 5的数 打表

    只包含因子2 3 5的数 题目连接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1010 Description K的 ...

  4. <摘录>CentOS6.5下添加epel源

    0.安装yum优先级插件 yum install yum-priorities 1.epel简介: https://fedoraproject.org/wiki/EPEL/zh-cn rpm -Uvh ...

  5. Spring发送带附件邮件

    下面是一个例子使用Spring通过Gmail SMTP服务器来发送电子邮件附件.为了包含附件的电子邮件,你必须使用 Spring的JavaMailSender及MimeMessage 来代替 Mail ...

  6. 关于jQuery中的 offset() 和 position() 的用法

    ---恢复内容开始--- 在jQuery中有两个获取元素位置的方法offset()和position().position()方法是在1.2.6版本之后加入的,为什么要引入这个方法呢?这两个方法之间有 ...

  7. [js插件]分享一个文章内容信息提示插件Colortip

    引用 项目中需要一个信息提示的功能,就上网找了一个插件,发现colortip实现比较简单,就定了这个插件. 实现过程 官网:http://tutorialzine.com/2010/07/colort ...

  8. 要使用C#实现一个ActiveX控件

    要使用C#实现一个ActiveX控件,需要解决三个问题: 1.使.NET组件能够被COM调用 2.在客户机上注册后,ActiveX控件能通过IE的安全认证 3.未在客户机上注册时,安装包能通过IE的签 ...

  9. Cohen-SutherLand算法(编码算法)

    转自:http://my.oschina.net/liqiong/blog/4921 Cohen-SutherLand算法(编码算法)   基本思想:对于每条线段P1P2,分为三种情况处理: (1)若 ...

  10. Static Nested Class 和 Inner Class的不同?

    Nested Class (一般是C++的说法),Inner Class (一般是JAVA的说法).Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上. 注: 静态内部类(Inner ...