linux socket_stream,Linux socket类,支持AF_INET/AF_UNIX STREAM/DGRAM

学习python时发现,socket和SocketServer的方便快捷,于是研究了一下socket和SocketServer.py写了一下C++版本的。

陆续分享一下。

1. socket类socket_t

socket++.h

/* class socket_t

* Description

* Simulation to python socket class

* Author

* wfb

* Version

* 0.1.0

* 2010/7/25

*/

#ifndef __SOCKET_PLUS_H__

#define __SOCKET_PLUS_H__

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

namespace ss

{

// it's NOT defined in (JUST A MAGIC, don't know y)

const size_t UNIX_PATH_MAX = 108;

/* address_t

* host[string] for ipaddress in ip4, unix-domain in AF_UNIX (ip6 NOT SUPPOSED RIGHT NOW, it's easy to)

* port[ushort] invalid for AF_UNIX

*/

struct address_t

{

std::string host;

unsigned short port;

address_t():host(""), port(0){}

address_t(const std::string& h, unsigned short p) : host(h), port(p){}

address_t(const address_t& add) : host(add.host), port(add.port){}

};

/* class socket_t

* int create();

* int create_from(int fileno);

* int accept(socket_t& socket, address_t& address);

* int bind(address_t& address);

* int listen(int backlog=5);

* int connect(const address_t& address);

* int close();

* int setsockopt(int level, int optname, int optval);

* int getsockopt(int level, int optname, int& optval);

* int reuse_address(int on=1

* int linger(int timeout=5);

* int send();

* int recv();

* int sendto();

* int recvfrom();

* int setblocking(int on=1);

* int fileno()const{return m_fileno;}

* int last_errno()const;

* int makefile();

*/

class socket_t

{

public:

socket_t():m_fileno(-1), m_ref(NULL){}

socket_t(int family, int type, int proto)

: m_fileno(::socket(family, type, proto)), m_family(family), m_type(type), m_proto(proto), m_ref(new int(1))

{}

socket_t(int fileno, int* pref, int family, int type, int proto)

: m_fileno(fileno), m_family(family), m_type(type), m_proto(proto), m_ref(pref ? pref : new int(1))

{}

socket_t(socket_t& sock)

: m_fileno(sock.m_fileno), m_family(sock.m_family), m_type(sock.m_type), m_proto(sock.m_proto), m_ref(sock.m_ref)

{

ref();

}

socket_t& operator=(socket_t& sock);

~socket_t(){close();}

int create();

int create_from(int fileno);

int accept(socket_t& socket, address_t& address);

int bind(address_t& address);

int listen(int backlog=5);

int connect(const address_t& address);

int close();

int setsockopt(int level, int optname, int optval);

int getsockopt(int level, int optname, int& optval);

int reuse_address(int on=1){return setsockopt(SOL_SOCKET, SO_REUSEADDR, on);}

int linger(int timeout=5);

/* TODO

int send();

int recv();

int sendto();

int recvfrom();

*/

int setblocking(int on=1);

int fileno()const{return m_fileno;}

int last_errno()const{return m_errno;}

int makefile(){return 0;}

private:

int ref(){if(NULL==m_ref)return 0;return ++*m_ref;}

int dref(){if(NULL==m_ref)return 0;return --*m_ref;}

private:

int m_fileno;

int m_family;

int m_type;

int m_proto;

int m_errno;

int* m_ref;

};

} // namespace ss

#endif //__SOCKET_PLUS_H__

socket++.cpp

#include "socket++.h"

namespace ss

{

socket_t& socket_t::operator=(socket_t& sock)

{

if (this==&sock) return *this;

this->close();

m_family = sock.m_family;

m_type = sock.m_type;

m_proto = sock.m_proto;

m_fileno = sock.m_fileno;

m_ref = sock.m_ref;

ref();

return *this;

}

int socket_t::create_from(int fileno)

{

if (m_ref) return m_fileno;

m_fileno = fileno;

m_ref = new int(1);

return m_fileno;

}

int socket_t::close()

{

int ret = 0;

if (m_ref && dref()<=0)

{

delete m_ref;

m_ref = NULL;

ret = ::close(m_fileno);

m_fileno = -1;

}

return ret;

}

int socket_t::bind(address_t& address)

{

sockaddr_in addr_in;

sockaddr_un addr_un;

sockaddr* paddr = NULL;

socklen_t addrlen = 0;

if (AF_INET==m_family)

{

bzero(&addr_in, sizeof(addr_in));

addr_in.sin_port = ::htons(address.port);

addr_in.sin_family = m_family;

if ((::inet_pton(m_family, address.host.c_str(), &addr_in.sin_addr)<=0))

{

m_errno = errno;

return -1;

}

paddr = (sockaddr*)&addr_in;

addrlen = sizeof(addr_in);

}

else if (AF_UNIX==m_family)

{

bzero(&addr_un, sizeof(addr_un));

addr_un.sun_family = AF_UNIX;

strncpy(addr_un.sun_path, address.host.c_str(), std::min(UNIX_PATH_MAX-1, address.host.size()));

address.host = addr_un.sun_path;

paddr = (sockaddr*)&addr_un;

addrlen = sizeof(addr_un);

}

else // AF_INET6 NOT supported

{

return -1;

}

if (::bind(m_fileno, paddr, addrlen))

{

m_errno = errno;

return -1;

}

return 0;

}

int socket_t::listen(int backlog/*=5*/)

{

int ret = ::listen(m_fileno, backlog);

if (ret)

{

m_errno = errno;

}

return ret;

}

int socket_t::accept(socket_t& socket, address_t& address)

{

sockaddr_in addr_in;

sockaddr_un addr_un;

sockaddr* paddr = NULL;

socklen_t addrlen = 0;

if (AF_INET==m_family)

{

bzero(&addr_in, sizeof(addr_in));

paddr = (sockaddr*)&addr_in;

addrlen = sizeof(addr_in);

}

else if (AF_UNIX==m_family)

{

bzero(&addr_un, sizeof(addr_un));

paddr = (sockaddr*)&addr_un;

addrlen = sizeof(addr_un);

}

int fd = ::accept(m_fileno, paddr, &addrlen);

if (fd>0)

{

if (AF_INET==m_family)

{

address.host = std::string(::inet_ntoa(addr_in.sin_addr));

address.port = ::ntohs(addr_in.sin_port);

}

else if (AF_UNIX==m_family)

{

address.host = addr_un.sun_path;

}

else

{

return -1;

}

socket_t client_sock(fd, NULL, m_family, m_type, m_proto);

socket = client_sock;

}

return fd;

}

int socket_t::connect(const address_t& address)

{

sockaddr_in addr_in;

sockaddr_un addr_un;

sockaddr* paddr = NULL;

socklen_t addrlen = 0;

if (m_family==AF_INET||m_family==AF_INET6)

{

bzero(&addr_in, sizeof(addr_in));

addr_in.sin_port = ::htons(address.port);

addr_in.sin_family = m_family;

if ((::inet_pton(m_family, address.host.c_str(), &addr_in.sin_addr)<=0))

{

m_errno = errno;

return -1;

}

paddr = (sockaddr*)&addr_in;

addrlen = sizeof(addr_in);

}

else if (m_family==AF_UNIX)

{

bzero(&addr_un, sizeof(addr_un));

addr_un.sun_family = AF_UNIX;

strncpy(addr_un.sun_path, address.host.c_str(), std::min(UNIX_PATH_MAX-1, address.host.size()));

paddr = (sockaddr*)&addr_un;

addrlen = sizeof(addr_un);

}

else // AF_INET6 NOT supported

{

return -1;

}

if (::connect(m_fileno, paddr, addrlen))

{

m_errno = errno;

return -1;

}

return 0;

}

int socket_t::setsockopt(int level, int optname, int optval)

{

int ret = ::setsockopt(m_fileno, level, optname, &optval, sizeof(optval));

if (ret)

{

m_errno = errno;

}

return ret;

}

int socket_t::getsockopt(int level, int optname, int& optval)

{

socklen_t optlen = sizeof(optval);

int ret = ::getsockopt(m_fileno, level, optname, &optval, &optlen);

if (ret)

{

m_errno = errno;

}

return ret;

}

int socket_t::setblocking(int on/*=1*/)

{

int ret = 0;

int val = 0;

if ((val = ::fcntl(m_fileno, F_GETFL)) == -1 && errno)

{

m_errno = errno;

return -1;

}

switch (on)

{

case 0:

if (val & O_NONBLOCK)

{

ret = ::fcntl(m_fileno, F_SETFL, 0);

}

break;

default:

if (!(val & O_NONBLOCK))

{

ret = ::fcntl(m_fileno, F_SETFL, 1);

}

break;

}

if (ret)

{

m_errno = errno;

}

return ret;

}

int socket_t::linger(int timeout/*=5*/)

{

struct linger lg;

lg.l_onoff=timeout>0?1:0;

lg.l_linger=timeout;

int ret = ::setsockopt(m_fileno, SOL_SOCKET, SO_LINGER, &lg, sizeof(lg));

if (ret)

{

m_errno = errno;

}

return ret;

}

} //namespace ss

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值