前面分析了对socket基本操作的封装,并按照数据的传送方式写了两个类,本篇将写一个代理类提供给库的使用者使用的类。
/***************************************************************************************
****************************************************************************************
* FILE : socket.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/11 Initial Version
****************************************************************************************
****************************************************************************************/
#ifndef _SOCKET_H_
#define _SOCKET_H_
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "sock_ev.h"
class EventLoop;
class CommBase;
class SockAddr;
/*==================================================================
* Function : Socket
* Description : Socket used for app, adapter CommBase
==================================================================*/
class Socket
{
public:
/*==================================================================
* Function : Socket.create
* Description : static function used for create Socket,
* Return Value: Socket pointer
==================================================================*/
static Socket* create();
/*==================================================================
* Function : Socket.destroy
* Description : static function used for destroy Socket created by Socket.create
* Input Para : sock_--socket pointer
==================================================================*/
static void destroy(Socket* &sock_);
/*==================================================================
* Function : Socket.getFd
* Description : get socket fd
* Return Value: socket fd,if fd is not avaliable -1 is return
==================================================================*/
int getFd();
/*==================================================================
* Function : Socket.open
* Description : open socket in server of unconnection-mode
* Input Para : socket address uri
* Return Value: if success return true, or else false is return
==================================================================*/
bool open(const char *uri_);
/*==================================================================
* Function : Socket.connect
* Description : connection-mode client connect to server
* Input Para : socket address uri
* Return Value: if success return true, or else false is return
==================================================================*/
bool connect(const char *uri_);
/*==================================================================
* Function : Socket.accept
* Description : connection-mode server accept client connection
* Input Para : sock_--stand for client socket pointer
* Return Value: if success return true, or else false is return
==================================================================*/
bool accept(Socket *sock_);
/*==================================================================
* Function : Socket.send
* Description : send data
* Input Para : data_--data pointer
* Input Para : len_--data length
* Return Value: the number of characters sent
==================================================================*/
int send(void *data_,
uint32_t len_);
/*==================================================================
* Function : Socket.send
* Description : send data
* Input Para : data_--data pointer
* Input Para : len_--data length
* Input Para : to_--the address of the target
* Return Value: the number of characters sent
==================================================================*/
int send(void *data_,
uint32_t len_,
const char *to_);
/*==================================================================
* Function : Socket.recv
* Description : recv data
* Input Para : data_--data pointer
* Input Para : len_--data length
* Return Value: the number of characters received
==================================================================*/
int recv(void *data_,
uint32_t len_);
/*==================================================================
* Function : Socket.recv
* Description : recv data
* Input Para : data_--data pointer
* Input Para : len_--data length
* Input Para : from_--the address of the source
* Return Value: the number of characters received
==================================================================*/
int recv(void *data_,
uint32_t len_,
char *from_);
/*==================================================================
* Function : Socket.getEvt
* Description : get event type
* Return Value: already register event
==================================================================*/
EventType getEvt();
/*==================================================================
* Function : Socket.processEvent
* Description : process Event
* Input Para : evt_--event
==================================================================*/
void processEvent(EventType evt_);
/*==================================================================
* Function : Socket.setCallBack
* Description : set calback function
==================================================================*/
void setCallBack(EventLoop *loop_,
EvCallBack cb_,
EventType evt_,
void *arg_);
/*==================================================================
* Function : Socket.clearCallBack
* Description : clear calback function
==================================================================*/
void clearCallBack(EventType evt_);
private:
EventType evt;
CommBase *comm;
SockAddr *addr;
EventLoop *loop;
EvCallBack rdCb;
EvCallBack wrCb;
void *rdArg;
void *wrArg;
// Disable copy construction and assignment.
Socket();
virtual ~Socket();
Socket(const Socket&);
const Socket &operator = (const Socket&);
};
#endif /*_SOCKET_H_*/
上面是头文件有比较详细的注释,通过函数名也可以看出函数的意义。
/***************************************************************************************
****************************************************************************************
* FILE : socket.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/11 Initial Version
****************************************************************************************
****************************************************************************************/
#include "socket.h"
#include "sock_ev.h"
#include "socket_addr.h"
#include "socket_base.h"
using namespace std;
Socket::Socket()
{
evt = 0;
comm = NULL;
addr = NULL;
loop = NULL;
rdCb = NULL;
wrCb = NULL;
rdArg= NULL;
wrArg= NULL;
}
Socket::~Socket()
{
if(NULL != comm) delete comm;
if(NULL != addr) delete addr;
}
Socket* Socket::create()
{
Socket *sock = new Socket();
if(NULL == sock)
{
logTrace("new Socket() failed");
return NULL;
}
return sock;
}
void Socket::destroy(Socket* &sock_)
{
if(NULL != sock_) delete sock_;
sock_ = NULL;
}
int Socket::getFd()
{
return comm->getSockFd();
}
bool Socket::open(const char *uri_)
{
addr = new SockAddr(uri_);
if(NULL == addr)
{
logTrace("new SockAddr(%s) failed", uri_);
return false;
}
if(!addr->parseUri())
{
logTrace("parseUri() failed;uri:%s", uri_);
return false;
}
int type = addr->getType();
if(SOCK_STREAM == type)
{
comm = new StreamSock();
}
else if(SOCK_DGRAM == type)
{
comm = new DgramSock();
}
else
{
logTrace("addr.type is invalid;type:%s", type);
return false;
}
if(NULL == comm)
{
logTrace("new StreamSock() failed");
return false;
}
if(!comm->openSock(*addr))
{
logTrace("StreamSock.openSock() failed");
return false;
}
return true;
}
bool Socket::connect(const char *uri_)
{
addr = new SockAddr(uri_);
if(NULL == addr)
{
logTrace("new SockAddr(%s) failed", uri_);
return false;
}
if(!addr->parseUri())
{
logTrace("parseUri() failed;uri:%s", uri_);
return false;
}
int type = addr->getType();
if(SOCK_STREAM == type)
{
comm = new StreamSock();
}
else if(SOCK_DGRAM == type)
{
comm = new DgramSock();
}
else
{
logTrace("addr.type is invalid;type:%s", type);
return false;
}
if(NULL == comm)
{
logTrace("new StreamSock() failed");
return false;
}
if(!comm->connectTo(*addr))
{
logTrace("StreamSock.connectTo() failed");
return false;
}
return true;
}
bool Socket::accept(Socket *sock_)
{
sock_->addr = new SockAddr(addr->getDomain(), addr->getType());
if(NULL == sock_->addr)
{
logTrace("new SockAddr(%d, %d) failed", addr->getDomain(), addr->getType());
return false;
}
int acceptFd = comm->acceptSock(*(sock_->addr));
if(-1 == acceptFd)
{
logTrace("accetp connection is failed");
return false;
}
int type = addr->getType();
if(SOCK_STREAM == type)
{
sock_->comm = new StreamSock();
}
else if(SOCK_DGRAM == type)
{
sock_->comm = new DgramSock();
}
else
{
logTrace("addr.type is invalid;type:%s", type);
return false;
}
if(NULL == sock_->comm)
{
logTrace("new StreamSock() failed");
return false;
}
sock_->comm->setSockFd(acceptFd);
return true;
}
int Socket::send(void *data_,
uint32_t len_)
{
return comm->sendData(data_, len_);
}
int Socket::send(void *data_,
uint32_t len_,
const char *to_)
{
SockAddr *tmpAddr = new SockAddr(to_);
if(NULL == tmpAddr)
{
logTrace("new SockAddr(%s) failed", to_);
return -1;
}
if(!tmpAddr->parseUri())
{
logTrace("parseUri() failed;uri:%s", to_);
delete tmpAddr;
return false;
}
int sendLen = comm->sendData(data_, len_, *tmpAddr);
delete tmpAddr;
return sendLen;
}
int Socket::recv(void *data_,
uint32_t len_)
{
return comm->recvData(data_, len_);
}
int Socket::recv(void *data_,
uint32_t len_,
char *from_)
{
SockAddr *tmpAddr = new SockAddr(addr->getDomain(), addr->getType());
if(NULL == tmpAddr)
{
logTrace("new SockAddr(%s) failed");
return -1;
}
int sendLen = comm->recvData(data_, len_, *tmpAddr);
if(NULL != from_)
{
string tmpStr;
if(tmpAddr->toStr(tmpStr))
{
sprintf(from_, "%s", tmpStr.c_str());
}
else
{
sprintf(from_, "%s", "Invalid socket address string");
}
}
delete tmpAddr;
return sendLen;
}
EventType Socket::getEvt()
{
return evt;
}
void Socket::processEvent(EventType evt_)
{
if(NULL != rdCb && evt_&evRead)
{
rdCb(loop, this, evRead, rdArg);
}
else if(NULL != wrCb && evt_&evWrite)
{
wrCb(loop, this, evWrite, wrArg);
}
else
{
logTrace("eventType:%d;reCb:%p,wrCb:%p", evt_, rdCb, wrCb);
}
}
void Socket::setCallBack(EventLoop *loop_,
EvCallBack cb_,
EventType evt_,
void *arg_)
{
loop = loop_;
if(evt_& evRead)
{
evt |= evRead;
rdCb = cb_;
rdArg= arg_;
}
if(evt_& evWrite)
{
evt |= evWrite;
wrCb = cb_;
wrArg= arg_;
}
}
void Socket::clearCallBack(EventType evt_)
{
if(evt_&evRead)
{
evt &= ~evRead;
rdCb = NULL;
rdArg= NULL;
}
if(evt_&evWrite)
{
evt &= ~evRead;
wrCb = NULL;
wrArg= NULL;
}
if(0 == evt)
{
loop = NULL;
}
}
基本上就是对前篇中封装的两个类的调用,字节流与数据包的区分在open、connect、accept三个函数中有所处理。