sock_ev——linux平台socket事件框架(uri地址的解析)

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

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

 

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



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值