跨平台Socket封装——CSocketImpl类

头文件SocketImpl.h

namespace LinWin
{
    class CSocketImpl
    {
    private:
        net_socket_fd m_sock;
        bool          m_bBlocking;

    public:
        CSocketImpl();
        CSocketImpl(net_socket_fd sockfd);
        CSocketImpl(const CSocketImpl& iml);
        virtual ~CSocketImpl();

    public:
        virtual int Create(int af = AF_INET, int type = SOCK_STREAM, int proto = 0);

        virtual void Close();

        virtual int Bind(const CSocketAddress& address);

        virtual int Listen(int backlog = 64);

        virtual int Accept(CSocketImpl* connfd, CSocketAddress& clientAddr);

        virtual int Connect(const CSocketAddress& addr);

        virtual int SendBytes(const void* lpBuf, unsigned int lpLen, int flag = 0);
        virtual int RecvBytes(void* lpBuf, unsigned int lpLen, int flag = 0);

        virtual int SendBytesto(const void* lpBuf, unsigned int lpLen, const CSocketAddress& addr, int flag = 0);
        virtual int RecvBytesfrom(void* lpBuf, unsigned int lpLen, CSocketAddress& addr, int flag = 0);

        virtual int ShutdownReceive();
        virtual int ShutdownSend();
        virtual int Shutdown();

        virtual int SetSendBufferSize(int size);
        virtual int GetSendBufferSize(int& size);

        virtual int SetReceiveBufferSize(int size);
        virtual int GetReceiveBufferSize(int& size);

        virtual int LocalAddress(CSocketAddress& localAddr);
        virtual int RemoteAddress(CSocketAddress& remoteAddr);

        virtual int Available(int& result);

        int SetOption(int level, int option, int value);
        int SetOption(int level, int option, unsigned value);
        int SetOption(int level, int option, unsigned char value);
        virtual int SetRawOption(int level, int option, const void* value, int length);

        int GetOption(int level, int option, int& value);
        int GetOption(int level, int option, unsigned& value);
        int GetOption(int level, int option, unsigned char& value);
        virtual int GetRawOption(int level, int option, void* value, int length);

        int SetLinger(bool on, int seconds);
        int GetLinger(bool& on, int& seconds);

        int SetNoDelay(bool flag);
        int GetNoDelay(bool& flag);

        int SetKeepAlive(bool flag);
        int GetKeepAlive(bool& flag);

        int SetReuseAddress(bool flag);
        int GetReuseAddress(bool& flag);

        virtual int SetBlocking(bool flag);
        virtual bool GetBlocking() const;

        net_socket_fd Sockfd() const;
        const net_socket_fd* Handle() const
        {
            return reinterpret_cast<const net_socket_fd*>(&m_sock);
        }

        int SocketError();

        virtual int Ioctl(net_ioctl_request_t request, int& arg);
        virtual int Ioctl(net_ioctl_request_t request, void* arg);
    }
}

Socket网络编程最基本的操作都封装在这里了,随后再把扩展的加进来。net_socket_fd类型的定义是为了统一平台之间的差异,它的定义已在platform.h文件中更新(在之前博客中)。

SocketImpl.cpp文件

#include "SocketImpl.h"

LinWin::CSocketImpl::CSocketImpl() : m_sock(NET_INVALID_SOCKET), m_bBlocking(false)
{

}

LinWin::CSocketImpl::CSocketImpl(net_socket_fd sock) : m_sock(sock), m_bBlocking(false)
{

}

LinWin::CSocketImpl::CSocketImpl(const CSocketImpl& iml) : m_sock(iml.m_sock), m_bBlocking(iml.m_bBlocking)
{

}

LinWin::CSocketImpl::~CSocketImpl()
{
    Close();
}

int LinWin::CSocketImpl::Create(int af /* = AF_INET */, int type /* = SOCK_STREAM */, int proto /* = 0 */)
{
    m_sock = ::socket(af, type, proto);

    return m_sock == NET_INVALID_SOCKET ? -1 : 0;
}

void LinWin::CSocketImpl::Close()
{
    if (m_sock != NET_INVALID_SOCKET)
    {
        closesocket(m_sock);
        m_sock = NET_INVALID_SOCKET;
    }
}

int LinWin::CSocketImpl::Bind(const CSocketAddress& address)
{
    if (m_sock == NET_INVALID_SOCKET)
        return -2;

    if (::bind(m_sock, reinterpret_cast<const struct sockaddr *>(address.GetAddress()), address.AddressLength()) != 0)
        return -1;

    return 0;
}

int LinWin::CSocketImpl::Listen(int backlog /* = 64 */)
{
    if (m_sock == NET_INVALID_SOCKET)
        return -2;

    if (::listen(m_sock, backlog) != 0)
        return -1;

    return 0;
}

int LinWin::CSocketImpl::Accept(CSocketImpl* connfd, CSocketAddress& clientAddr)
{
    if (m_sock == NET_INVALID_SOCKET || connfd == NULL)
        return -2;

    socklen_t salen = clientAddr.AddressLength();
    connfd->m_sock = ::accept(m_sock, reinterpret_cast<struct sockaddr*>(clientAddr.GetAddress()), &salen);
    if (connfd->m_sock == NET_INVALID_SOCKET)
        return -1;

    return 0;
}

int LinWin::CSocketImpl::Connect(const CSocketAddress& addr)
{
    if (m_sock == NET_INVALID_SOCKET)
        return -2;

    if (::connect(m_sock, reinterpret_cast<const struct sockaddr *>(addr.GetAddress()), addr.AddressLength()) != 0)
        return -1;

    return 0;
}

int LinWin::CSocketImpl::SendBytes(const void* lpBuf, unsigned int lpLen, int flag)
{
    return ::send(m_sock, reinterpret_cast<const char*>(lpBuf), lpLen, flag);
}

int LinWin::CSocketImpl::RecvBytes(void* lpBuf, unsigned int lpLen, int flag)
{
    return ::recv(m_sock, reinterpret_cast<char*>(lpBuf), lpLen, flag);
}

int LinWin::CSocketImpl::SendBytesto(const void* lpBuf, unsigned int lpLen, const CSocketAddress& addr, int flag)
{
    return ::sendto(m_sock, reinterpret_cast<const char*>(lpBuf), lpLen, flag,
        reinterpret_cast<const struct sockaddr*>(addr.GetAddress()), addr.AddressLength());
}

int LinWin::CSocketImpl::RecvBytesfrom(void* lpBuf, unsigned int lpLen, CSocketAddress& addr, int flag)
{
    socklen_t addrLen = addr.AddressLength();
    return ::recvfrom(m_sock, reinterpret_cast<char*>(lpBuf), lpLen, flag, 
        reinterpret_cast<sockaddr*>(addr.GetAddress()), &addrLen);
}

int LinWin::CSocketImpl::ShutdownReceive()
{
    return (::shutdown(m_sock, SD_RECEIVE) != 0) ? -1 : 0;
}

int LinWin::CSocketImpl::ShutdownSend()
{   
    return (::shutdown(m_sock, SD_SEND) != 0) ? -1 : 0;
}

int LinWin::CSocketImpl::Shutdown()
{
    return (::shutdown(m_sock, SD_BOTH) != 0) ? -1 : 0;
}

int LinWin::CSocketImpl::SetSendBufferSize(int size)
{
    return SetOption(SOL_SOCKET, SO_SNDBUF, size);
}

int LinWin::CSocketImpl::GetSendBufferSize(int& size)
{
    return GetOption(SOL_SOCKET, SO_SNDBUF, size);
}

int LinWin::CSocketImpl::SetReceiveBufferSize(int size)
{
    return SetOption(SOL_SOCKET, SO_RCVBUF, size);
}

int LinWin::CSocketImpl::GetReceiveBufferSize(int& size)
{
    return GetOption(SOL_SOCKET, SO_RCVBUF, size);
}

int LinWin::CSocketImpl::LocalAddress(CSocketAddress& localAddr)
{
    socklen_t saLen = sizeof(struct sockaddr_in);
    int rc = ::getsockname(m_sock, reinterpret_cast<struct sockaddr*>(localAddr.GetAddress()), &saLen);

    return rc != 0 ? -1 : 0;
}

int LinWin::CSocketImpl::RemoteAddress(CSocketAddress& remoteAddr)
{
    socklen_t saLen = sizeof(struct sockaddr_in);
    int rc = ::getpeername(m_sock, reinterpret_cast<struct sockaddr*>(remoteAddr.GetAddress()), &saLen);

    return rc != 0 ? -1 : 0;
}

int LinWin::CSocketImpl::Available(int& result)
{
    return Ioctl(FIONREAD, result);
}

int LinWin::CSocketImpl::SetOption(int level, int option, int value)
{
    return SetRawOption(level, option, &value, sizeof(value));
}

int LinWin::CSocketImpl::SetOption(int level, int option, unsigned value)
{
    return SetRawOption(level, option, &value, sizeof(value));
}

int LinWin::CSocketImpl::SetOption(int level, int option, unsigned char value)
{
    return SetRawOption(level, option, &value, sizeof(value));
}

int LinWin::CSocketImpl::SetRawOption(int level, int option, const void* value, int length)
{
    int rc = ::setsockopt(m_sock, level, option, reinterpret_cast<const char*>(value), (socklen_t)length);

    return rc == -1 ? -1 : 0;
}

int LinWin::CSocketImpl::GetOption(int level, int option, int& value)
{
    return GetRawOption(level, option, &value, sizeof(value));
}

int LinWin::CSocketImpl::GetOption(int level, int option, unsigned& value)
{
    return GetRawOption(level, option, &value, sizeof(value));
}

int LinWin::CSocketImpl::GetOption(int level, int option, unsigned char& value)
{
    return GetRawOption(level, option, &value, sizeof(value));
}

int LinWin::CSocketImpl::GetRawOption(int level, int option, void* value, int length)
{
    int rc = ::getsockopt(m_sock, level, option, reinterpret_cast<char*>(value), reinterpret_cast<socklen_t*>(&length));

    return rc == -1 ? -1 : 0;
}

int LinWin::CSocketImpl::SetLinger(bool on, int seconds)
{
    struct linger l;
    l.l_onoff = on ? 1 : 0;
    l.l_linger = seconds;
    return SetRawOption(SOL_SOCKET, SO_LINGER, &l, sizeof(l));
}

int LinWin::CSocketImpl::GetLinger(bool& on, int& seconds)
{
    struct linger l;
    int len = sizeof(l);
    int ret = GetRawOption(SOL_SOCKET, SO_LINGER, &l, len);
    if (ret == 0)
    {
        on = (l.l_onoff != 0);
        seconds = l.l_linger;
    }

    return ret;
}

int LinWin::CSocketImpl::SetNoDelay(bool flag)
{
    int value = flag ? 1 : 0;
    return SetOption(IPPROTO_TCP, TCP_NODELAY, value);
}

int LinWin::CSocketImpl::GetNoDelay(bool& flag)
{
    int value = 0;
    int ret = GetOption(IPPROTO_TCP, TCP_NODELAY, value);
    if (ret == 0)
        flag = (value != 0);

    return ret;
}

int LinWin::CSocketImpl::SetKeepAlive(bool flag)
{
    int value = flag ? 1 : 0;
    return SetOption(SOL_SOCKET, SO_KEEPALIVE, value);
}

int LinWin::CSocketImpl::GetKeepAlive(bool& flag)
{
    int value(0);
    int ret = GetOption(SOL_SOCKET, SO_KEEPALIVE, value);
    if (ret == 0)
        flag = (value != 0);

    return ret;
}

int LinWin::CSocketImpl::SetReuseAddress(bool flag)
{
    int value = flag ? 1 : 0;
    return SetOption(SOL_SOCKET, SO_REUSEADDR, value);
}

int LinWin::CSocketImpl::GetReuseAddress(bool& flag)
{
    int value(0);
    int ret = GetOption(SOL_SOCKET, SO_REUSEADDR, value);
    if (ret == 0)
        flag = (value != 0);

    return ret;
}

int LinWin::CSocketImpl::SetBlocking(bool flag)
{
#ifdef WINDOWS_FAMILY
    unsigned long nonblocking = flag ? 1 : 0;
    if (ioctlsocket(m_sock, FIONBIO, (unsigned long*)&nonblocking) == SOCKET_ERROR)
        return -1;
#else
    int opts;
    opts = fcntl(m_sock, F_GETFL);
    if (opts < 0)
        return -1;
    if (flag)
        opts = opts | O_NONBLOCK;
    else
        opts = opts & (~O_NONBLOCK);
    if (fcntl(m_sock, F_SETFL, opts) < 0)
        return -1;
#endif
    m_bBlocking = flag;

    return 0;
}

bool LinWin::CSocketImpl::GetBlocking() const
{
    return m_bBlocking;
}

net_socket_fd LinWin::CSocketImpl::Sockfd() const
{
    return m_sock;
}

int LinWin::CSocketImpl::Ioctl(net_ioctl_request_t request, int& arg)
{
    int rc;
#ifdef WINDOWS_FAMILY
    rc = ioctlsocket(m_sock, request, reinterpret_cast<u_long*>(&arg));
#else
    rc = ::ioctl(m_sock, request, &arg);
#endif

    return (rc != 0) ? -1 : 0;
}

int LinWin::CSocketImpl::Ioctl(net_ioctl_request_t request, void* arg)
{
    int rc;
#ifdef WINDOWS_FAMILY
    rc = ioctlsocket(m_sock, request, reinterpret_cast<u_long*>(arg));
#else
    rc = ::ioctl(m_sock, request, arg);
#endif

    return (rc != 0) ? -1 : 0;
}

int LinWin::CSocketImpl::SocketError()
{
#ifdef WINDOWS_FAMILY
    return GetLastError();
#else
    return errno;
#endif
}

由于CSocketAddress类中添加了一个非const版本的GetAddress成员函数,所以去掉此类中所有const_cast的转换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值