转: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字符串,主要用在采用数据包协议时需要获取对端地址的情况
上面的这个类对于使用者是不可见的,属于内部使用类。
转:sock_ev——linux平台socket事件框架(uri地址的解析) .的更多相关文章
- 转:sock_ev——linux平台socket事件框架(event loop) .
上一篇我们封装了三种事件监听方式,如果分别提供给客户端使用,有点不方便,也不利于统一管理:我们再封装一层EventLoop. /************************************ ...
- 转:sock_ev——linux平台socket事件框架(socket API的封装) .
把linux平台提供的有关socket操作的API进行封装是有必要的:基于stream操作的流程与基于dgram操作的流程略有不同,分别放在两个类中,但两者又有很多相似的操作,因此写一个基类,让其继承 ...
- 转:sock_ev——linux平台socket事件框架(event dispatcher) .
最近比较忙,好久没更新了:今天我们看一下事件的监听方式,在linux下面事件的监听方式有三种select.poll.epoll,性能上面epoll最高,如果仅是最多监听十多个描述符,用啥无所谓,如果是 ...
- 转:sock_ev——linux平台socket事件框架(基于字节流的测试程序) .
原文:http://blog.csdn.net/gdutliuyun827/article/details/8257186 由于工作与学习的需要,写了一个socket的事件处理框架,在公司写的已经使用 ...
- 转:sock_ev——linux平台socket事件框架(socket代理类) .
前面分析了对socket基本操作的封装,并按照数据的传送方式写了两个类,本篇将写一个代理类提供给库的使用者使用的类. /**************************************** ...
- 转:sock_ev——linux平台socket事件框架(基于数据报的测试程序) .
上一篇已经做过注释,这一篇直接上代码 /******************************************************************************** ...
- 转:sock_ev——linux平台socket事件框架(logTrace) .
写代码要有调试log,采用syslog的输出:一般会输出到"/var/log/messages" /**************************************** ...
- linux下内存大小、起始地址的解析与修改
在实际的工作中,由于产品型号的不同,经常需要调整linux所管理的内存的大小,而内核在启动阶段,会两次去解析从uboot传递过来的关于内存的信息,具体如下: 一.解析从uboot传递过来的tag(在p ...
- AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍
一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...
随机推荐
- JDK源码(1.7) -- java.util.AbstractCollection<E>
java.util.AbstractCollection<E> 源码分析(JDK1.7) ------------------------------------------------- ...
- Mysql -- 设置中国时区时间
Mysql -- 设置中国时区时间 查看mysql的时区设置 mysql> show variables like '%time_zone%'; 修改mysql的时区设置, 注:mysql ...
- js实现大转盘抽奖游戏实例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Get buck-boost performance from a boost regulator
The SEPIC (single-ended, primary-inductance-converter) topology is generally a good choice for volta ...
- TRF7970A IC Communication Interface
General Introduction The communication interface to the reader can be configured in two ways: with a ...
- ubuntu systemtap-sdt-dev
http://kr.archive.ubuntu.com/ubuntu/pool/universe/s/systemtap/systemtap-sdt-dev_3.0-7_amd64.deb
- hibernate将connection放进threadlocal里实现数据库连接池
Why ThreadLocal? 无论如何,要编写一个多线程安全(Thread-safe)的程序是困难的,为了让线程共享资源,必须小心地对共享资源进行同步,同步带来一定的效能延迟,而另一方面,在处理同 ...
- C语言宏定义和宏定义函数
要写好C语言,漂亮的宏定义是非常重要的.宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等. 在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定 ...
- 开源 免费 java CMS - FreeCMS1.5-数据对象-info
下载地址:http://code.google.com/p/freecms/ info 在信息页静态化时,系统会自动向模板文件传递currInfo对象,此对象存储当前信息.在使用信息相关标签时,标签会 ...
- docker基本元素和底层实现
docker是轻量级的操作系统虚拟化解决方案 优点 1.基于操作系统层面 2.启动速度快(秒级) 3.资源利用率高 4.性能高.易管理 docker有3大基本要素 分别是 1.镜像:只读模板,用来创建 ...