C++ Socket封装
来源:互联网 发布:单片机控制舵机程序 编辑:程序博客网 时间:2024/05/29 17:27
TC_Socket是一个socket的封装类,封装了socket的处理,该封装类的主要操作功能包括
- 生成socket,根据指定的socket类型,调用socket系统调用,并进行异常处理,如果sock存在,则先关闭,打开新的描述符。
void TC_Socket::createSocket( int iSocketType, int iDomain)
{
assert (iSocketType == SOCK_STREAM || iSocketType == SOCK_DGRAM);
close();
_iDomain = iDomain;
_sock = socket(iDomain, iSocketType , 0);
if( _sock < 0)
{
_sock = INVALID_SOCKET;
throw TC_Socket_Exception( "[TC_Socket::createSocket] create socket error! :" + string(strerror( errno)));
}
}
- 关闭sock;
void TC_Socket::close()
{
if ( _sock != INVALID_SOCKET)
{
:: close(_sock );
_sock = INVALID_SOCKET;
}
}
- 获取对点的ip和端口,对AF_INET的socket有效,构建sockaddr,利用getPeerName从sock描述符获取IP以及端口地址,通过inet_ntop把数值型地址转换为字符串,通过ntohs把端口的网络顺序转换成为主机顺序,sPeerAddress= sAddr是一个复制拷贝。
void TC_Socket:: getPeerName(string &sPeerAddress, uint16_t &iPeerPort)
{
assert (_iDomain == AF_INET);
struct sockaddr stPeer;
bzero (&stPeer, sizeof ( struct sockaddr));
socklen_t iPeerLen = sizeof (sockaddr );
getPeerName (&stPeer, iPeerLen);
char sAddr[ INET_ADDRSTRLEN] = "\0" ;
struct sockaddr_in *p = ( struct sockaddr_in *)&stPeer;
inet_ntop (_iDomain , &p->sin_addr, sAddr, sizeof(sAddr));
sPeerAddress= sAddr;
iPeerPort = ntohs(p->sin_port);
}
- 获取自己的ip和端口,对AF_INET的socket有效.
void TC_Socket:: getSockName(string &sSockAddress, uint16_t &iSockPort)
{
assert (_iDomain == AF_INET);
struct sockaddr stSock;
bzero (&stSock, sizeof ( struct sockaddr));
socklen_t iSockLen = sizeof (sockaddr );
getSockName (&stSock, iSockLen);
char sAddr[ INET_ADDRSTRLEN] = "\0" ;
struct sockaddr_in *p = ( struct sockaddr_in *)&stSock;
inet_ntop (_iDomain , &p->sin_addr, sAddr, sizeof(sAddr));
sSockAddress = sAddr;
iSockPort = ntohs(p->sin_port);
}
- 修改,获取socket选项值.
int TC_Socket:: setSockOpt( int opt, const void *pvOptVal, socklen_t optLen, int level)
{
return setsockopt(_sock , level, opt, pvOptVal, optLen);
}
int TC_Socket::getSockOpt( int opt, void *pvOptVal, socklen_t &optLen, int level)
{
return getsockopt(_sock , level, opt, pvOptVal, &optLen);
}
- accept服务端sock,accept是阻塞的操作,并是一个不可重入函数,会被信号处理等中断,此处需要重复操作,返回一个客户端TC_SOCK
int TC_Socket:: accept(TC_Socket &tcSock, struct sockaddr *pstSockAddr, socklen_t &iSockLen)
{
assert (tcSock._sock == INVALID_SOCKET);
int ifd;
while ((ifd = :: accept(_sock , pstSockAddr, &iSockLen)) < 0 && errno == EINTR);
tcSock. _sock = ifd;
tcSock. _iDomain = _iDomain;
return tcSock. _sock;
}
- bind操作,将sock绑定到指定的地址与端口
void TC_Socket:: bind( const char *sPathName)
{
assert (_iDomain == AF_LOCAL);
unlink (sPathName);
struct sockaddr_un stBindAddr;
bzero (&stBindAddr, sizeof ( struct sockaddr_un));
stBindAddr. sun_family = _iDomain ;
strncpy (stBindAddr.sun_path, sPathName, sizeof (stBindAddr.sun_path));
try
{
bind(( struct sockaddr *)&stBindAddr, sizeof (stBindAddr));
}
catch(...)
{
throw TC_Socket_Exception( "[TC_Socket::bind] bind '" + string(sPathName) + "' error", errno);
}
}
void TC_Socket::bind( struct sockaddr * pstBindAddr, socklen_t iAddrLen)
{
//如果服务器终止后,服务器可以第二次快速启动而不用等待一段时间
int iReuseAddr = 1;
//设置
setSockOpt (SO_REUSEADDR, ( const void *)&iReuseAddr, sizeof (int ), SOL_SOCKET);
if(:: bind(_sock , pstBindAddr, iAddrLen) < 0)
{
throw TC_Socket_Exception( "[TC_Socket::bind] bind error", errno );
}
}
- 连接其他服务,对AF_INET的socket有效(同步连接)
int TC_Socket::connect( struct sockaddr *pstServerAddr, socklen_t serverLen)
{
return :: connect(_sock , pstServerAddr, serverLen);
}
- 监听其他端口(同步连接),能收指定连接队列
void TC_Socket::listen( int iConnBackLog)
{
if (:: listen(_sock , iConnBackLog) < 0)
{
throw TC_Socket_Exception( "[TC_Socket::listen] listen error", errno );
}
}
- 发送,接收数据(一般用于tcp).
int TC_Socket::recv( void *pvBuf, size_t iLen, int iFlag)
{
return :: recv(_sock , pvBuf, iLen, iFlag);
}
int TC_Socket::send( const void *pvBuf, size_t iLen, int iFlag)
{
return :: send(_sock , pvBuf, iLen, iFlag);
}
- 单向关闭连接
void TC_Socket:: shutdown( int iHow)
{
if (:: shutdown(_sock , iHow) < 0)
{
throw TC_Socket_Exception( "[TC_Socket::shutdown] shutdown error", errno );
}
}
- 设置是否阻塞,利用fcntl,先F_GETFL操作,加上或者消除bBlock后F_SETFL
void TC_Socket:: setblock( int fd, bool bBlock)
{
int val = 0;
if ((val = fcntl(fd, F_GETFL, 0)) == -1)
{
throw TC_Socket_Exception( "[TC_Socket::setblock] fcntl [F_GETFL] error", errno );
}
if(!bBlock)
{
val |= O_NONBLOCK;
}
else
{
val &= ~ O_NONBLOCK;
}
if ( fcntl(fd, F_SETFL, val) == -1)
{
throw TC_Socket_Exception( "[TC_Socket::setblock] fcntl [F_SETFL] error", errno );
}
}
- 静态工具方法,生成管道,并且将管道设置的读写设置为指定的阻塞设置。
void TC_Socket:: createPipe( int fds[2], bool bBlock)
{
if(:: pipe(fds) != 0)
{
throw TC_Socket_Exception( "[TC_Socket::createPipe] error", errno );
}
try
{
setblock(fds[0], bBlock);
setblock(fds[1], bBlock);
}
catch(...)
{
:: close(fds[0]);
:: close(fds[1]);
throw;
}
}
- 静态工具方法,获取所有本地地址,主要借助于ioctl函数,不断的递增分配存储空间,直到空间能够容纳所有的地址为止,表示取到了所有的地址;
vector< string> TC_Socket:: getLocalHosts()
{
vector <string> result;
TC_Socket ts;
ts.createSocket (SOCK_STREAM, AF_INET);
int cmd = SIOCGIFCONF;
struct ifconf ifc;
int numaddrs = 10;
int old_ifc_len = 0;
while( true)
{
int bufsize = numaddrs * static_cast< int>( sizeof( struct ifreq));
ifc. ifc_len = bufsize;
ifc. ifc_buf = ( char*)malloc (bufsize);
int rs = ioctl(ts.getfd(), cmd, &ifc);
if(rs == -1)
{
free(ifc.ifc_buf );
throw TC_Socket_Exception ("[TC_Socket::getLocalHosts] ioctl error" , errno);
}
else if(ifc. ifc_len == old_ifc_len)
{
break;
}
else
{
old_ifc_len = ifc. ifc_len;
}
numaddrs += 10;
free(ifc.ifc_buf);
}
numaddrs = ifc. ifc_len / static_cast< int>( sizeof( struct ifreq));
struct ifreq* ifr = ifc. ifc_req;
for( int i = 0; i < numaddrs; ++i)
{
if(ifr[i]. ifr_addr.sa_family == AF_INET)
{
struct sockaddr_in* addr = reinterpret_cast< struct sockaddr_in*>(&ifr[i]. ifr_addr);
if(addr-> sin_addr.s_addr != 0)
{
char sAddr[ INET_ADDRSTRLEN] = "\0";
inet_ntop(AF_INET , &(*addr).sin_addr, sAddr, sizeof (sAddr));
result.push_back (sAddr);
}
}
}
free (ifc.ifc_buf);
return result;
}
- 静态工具方法,解析地址, 从字符串(ip或域名), 解析到in_addr结构.
void TC_Socket:: parseAddr( const string &sAddr, struct in_addr &stSinAddr)
{
int iRet = inet_pton(AF_INET, sAddr. c_str(), &stSinAddr);
if(iRet < 0)
{
throw TC_Socket_Exception( "[TC_Socket::parseAddr] inet_pton error", errno );
}
else if(iRet == 0)
{
struct hostent stHostent;
struct hostent *pstHostent;
char buf[2048] = "\0";
int iError;
gethostbyname_r(sAddr.c_str(), &stHostent, buf, sizeof (buf), &pstHostent, &iError);
if (pstHostent == NULL)
{
throw TC_Socket_Exception( "[TC_Socket::parseAddr] gethostbyname_r error! :" + string(hstrerror(iError)));
}
else
{
stSinAddr = *( struct in_addr *) pstHostent-> h_addr;
}
}
}
0 0
- Socket封装
- C语言的socket封装库-waisock编程简介
- 自己封装socket
- 事件模型SOCKET封装
- Socket封装2
- Socket封装3
- Socket封装4
- Socket封装5
- Socket封装6
- Socket封装7
- Socket封装7
- Socket封装8
- Socket封装9
- Socket封装10
- Socket封装11
- Socket封装12
- 跨平台Socket封装
- 跨平台Socket封装
- reason about thread is blocked
- 241. Different Ways to Add Parentheses
- Reflect反射的基础知识
- 多态
- Qt官方开发环境生成的exe发布方式--使用windeployqt(转载于百度winland0704)
- C++ Socket封装
- 护照阅读芯片读取技术SDK
- JDBC API
- MySQL
- 二,Eclipse的egit插件冲突合并方法
- nginx的部署学习
- unity—NGUI播放视频及声音注意事项
- poj 3345 树形dp
- [BZOJ1786&&BZOJ1831]配对 dp