跨平台Socket封装——CTcpClient类

TcpClient.h

#ifndef __TCPSERVER_H__
#define __TCPSERVER_H__

namespace LinWin
{
    class CSocketImpl;
    class CSocketAddress;

    class CTcpClient
    {
    private:
        int m_SndTimeOut;
        int m_RcvTimeOut;
        CSocketImpl* m_sock;

    public:
        CTcpClient();
        CTcpClient(CSocketImpl* sock);
        ~CTcpClient();

        int Create(bool bAccept = false);
        void Close();
        int Connect(const CSocketAddress& addr);

        int SetSendTimeOut(int timeout);
        int SetRecvTimeOut(int timeout);
        int SetSendBufferSize(int size);
        int SetRecvBufferSize(int size);

        int Send(const void* lpBuf, unsigned int len);
        int Recv(void*lpBuf, unsigned int len);
        int Sendn(const void* lpBuf, unsigned int len);
        int Recvn(void*lpBuf, unsigned int len);
        int ReadLine(void*lpBuf, unsigned int len);

        net_socket_fd Sockfd() const;
        CSocketImpl* Handle();

    private:
        int RealSend(const void*lpBuf, unsigned int len);
        int RealRecv(void* lpBuf, unsigned int len);
    };
}

#endif

TcpClient.cpp类

#include "Platform.h"
#include "SocketImpl.h"
#include "TcpClient.h"

//////////////////////////////////////////////////////////////////////////
LinWin::CTcpClient::CTcpClient() : m_SndTimeOut(NET_INFINITE), m_RcvTimeOut(NET_INFINITE), m_sock(NULL)
{

}

LinWin::CTcpClient::CTcpClient(CSocketImpl* sock) : m_SndTimeOut(NET_INFINITE), m_RcvTimeOut(NET_INFINITE), m_sock(sock)
{

}

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

int LinWin::CTcpClient::Create(bool bAccept/* = false */)
{
    if (!m_sock)
    {
        m_sock = new CSocketImpl;
        if (!m_sock)
            return -1;
        if (!bAccept)
            return m_sock->Create();
    }

    return 0;
}

void LinWin::CTcpClient::Close()
{
    if (m_sock)
    {
        m_sock->Close();
        delete m_sock;
        m_sock = NULL;
    }
}

int LinWin::CTcpClient::Connect(const CSocketAddress& addr)
{
    if (Create() != 0)
        return -1;

    return m_sock->Connect(addr);
}

int LinWin::CTcpClient::SetSendTimeOut(int timeout)
{
    if (Create() != 0)
        return -1;

    if (timeout < 0)
        timeout = NET_INFINITE;

    m_SndTimeOut = timeout;

#ifdef WINDOWS_FAMILY
    return m_sock->SetRawOption(SOL_SOCKET, SO_SNDTIMEO, &m_SndTimeOut, sizeof(m_SndTimeOut));
#else
    struct timeval tv;
    tv.tv_sec = m_SndTimeOut / 1000;
    tv.tv_usec = m_SndTimeOut % 1000 * 1000;
    return m_sock->SetRawOption(SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval));
#endif  
}

int LinWin::CTcpClient::SetRecvTimeOut(int timeout)
{
    if (Create() != 0)
        return -1;

    if (timeout < 0)
        timeout = NET_INFINITE;

    m_RcvTimeOut = timeout;

#ifdef WINDOWS_FAMILY
    return m_sock->SetRawOption(SOL_SOCKET, SO_RCVTIMEO, &m_RcvTimeOut, sizeof(m_RcvTimeOut));
#else
    struct timeval tv;
    tv.tv_sec = m_SndTimeOut / 1000;
    tv.tv_usec = m_SndTimeOut % 1000 * 1000;
    return m_sock->SetRawOption(SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
#endif
}

int LinWin::CTcpClient::SetSendBufferSize(int size)
{
    if (Create() != 0)
        return -1;

    return m_sock->SetOption(SOL_SOCKET, SO_SNDBUF, size);
}

int LinWin::CTcpClient::SetRecvBufferSize(int size)
{
    if (Create() != 0)
        return -1;

    return m_sock->SetOption(SOL_SOCKET, SO_RCVBUF, size);
}

int LinWin::CTcpClient::Send(const void* lpBuf, unsigned int len)
{
    return RealSend(lpBuf, len);
}

int LinWin::CTcpClient::Recv(void* lpBuf, unsigned int len)
{
    return RealRecv(lpBuf, len);
}

int LinWin::CTcpClient::Sendn(const void* lpBuf, unsigned int len)
{
    unsigned int offset = 0;
    const char* ptr = reinterpret_cast<const char*>(lpBuf);
    int ret = NET_NO_ERROR;
    do
    {
        ret = RealSend(ptr, len - offset);
        if (ret != NET_SOCKET_ERROR)
        {
            offset += ret;
            ptr += ret;
        }
        else break;
    } while (offset < len);

    return ret;
}

int LinWin::CTcpClient::Recvn(void* lpBuf, unsigned int len)
{
    unsigned int offset = 0;
    char* ptr = reinterpret_cast<char*>(lpBuf);
    int ret = NET_NO_ERROR;
    do
    {
        ret = RealRecv(ptr, len - offset);

        if (ret != NET_SOCKET_ERROR)
        {
            if (ret == 0)
                break;
            offset += ret;
            ptr += ret;
        }
        else break;
    } while (offset < len);

    return ret;
}

int LinWin::CTcpClient::ReadLine(void*lpBuf, unsigned int len)
{
    memset(lpBuf, 0, len);
    char* ptr = reinterpret_cast<char*>(lpBuf);
    unsigned int offset = 0;
    int ret = NET_NO_ERROR;
    do
    {
        ret = RealRecv(ptr, 1);
        if (ret != 1)
            break;
        char ch = *ptr;
        if (ch == '\n')
            break;
        offset++;
        ptr++;
    } while (offset < len);

    if (offset == len)
        ret = -1;

    return offset;
}

int LinWin::CTcpClient::RealSend(const void*lpBuf, unsigned int lpLen)
{
    return m_sock->SendBytes(lpBuf, lpLen, 0);
}

int LinWin::CTcpClient::RealRecv(void* lpBuf, unsigned int lpLen)
{
    return m_sock->RecvBytes(lpBuf, lpLen);
}

net_socket_fd LinWin::CTcpClient::Sockfd() const
{
    return m_sock->Sockfd();
}

LinWin::CSocketImpl* LinWin::CTcpClient::Handle()
{
    return m_sock;
}

设置发送超时和接收超时,Windows下单位是毫秒ms,Linux下是秒s。此实现,统一为毫秒单位。
2016/12/12修改ReadLine的返回值为offset。

你可能感兴趣的:(C/C++)