跨平台Socket封装——CTcpClient类

本文详细介绍了CTcpClient类的功能及使用方法,包括创建客户端、连接服务器、设置超时时间等,并提供了完整的类定义和成员函数说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值