Socket封装4

来源:互联网 发布:mdf数据格式文件 编辑:程序博客网 时间:2024/06/05 17:03

// #include <standard library headers>
#include <iostream>

// #include <other library headers>
#include <errno.h>
#include <fcntl.h>

// #include "customer headers"
#include "Socket.h"


namespace sock
{

    // statics
#ifdef _WIN32
    WSAInitial Socket::sWinsockInit;
#endif


    // ctor && dtor

    Socket::Socket()
        : mSock(INVALID_SOCKET)
    {
        memset(&mAddr, 0, sizeof(mAddr));
    }


    Socket::~Socket()
    {
        if (IsValid())
        {
            ::shutdown(mSock, SD_BOTH);
#ifdef WIN32
            ::closesocket(mSock);
#else
            ::close (mSock);
#endif
        }
    }


    bool Socket::Create()
    {
        mSock = socket(AF_INET, SOCK_STREAM, 0);
        if (!IsValid())
        {
            return false;
        }

        // TIME_WAIT - argh
        int on = 1;
        int ret = setsockopt(mSock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on));

        return (ret != SOCKET_ERROR);
    }


    bool Socket::Bind(const int port)
    {
        if (!IsValid())
        {
            return false;
        }

        mAddr.sin_family = AF_INET;
        mAddr.sin_addr.s_addr = INADDR_ANY;
        mAddr.sin_port = htons ( port );

        int ret = ::bind(mSock,
            (struct sockaddr*)&mAddr,
            sizeof(mAddr));

        return (ret != SOCKET_ERROR);
    }


    bool Socket::Listen() const
    {
        if (!IsValid())
        {
            return false;
        }

        int ret = ::listen(mSock, SOMAXCONN);
        return (ret != SOCKET_ERROR);
    }


    bool Socket::Accept(Socket& newSocket, int sec, int usec) const
    {
        int select = Select(true, sec, usec);
        if (select <= 0)
        {
            return false;
        }

        int addr_length = sizeof(sockaddr_in);
        newSocket.mSock = ::accept(mSock, (sockaddr*)&newSocket.mAddr, (socklen_t*)&addr_length);
#ifdef WIN32
        return (newSocket.mSock != INVALID_SOCKET);
#else
        return (newSocket.mSock > 0);
#endif
    }


    bool Socket::Send(const std::string s, int sec, int usec) const
    {
        return Send(s.c_str(), static_cast<int>(s.size()), sec, usec);
    }


    bool Socket::Send(const char* buf, int len, int sec, int usec) const
    {
        if (buf == NULL)
        {
            return false;
        }

        int select = Select(false, sec, usec);
        if (select <= 0)
        {
            return false;
        }

        int totalSendLen = 0;
        while (totalSendLen < len)
        {
            int leaveLen = len - totalSendLen;
            int s = (leaveLen < MAXSEND) ? leaveLen : MAXSEND;
            int sendLen = ::send(mSock, &buf[totalSendLen], s, 0);
            if (sendLen == SOCKET_ERROR)
            {
#ifdef _DEBUG
                GetLastError();
#endif
                return false;
            }
            std::cout << sendLen << std::endl;

            totalSendLen += sendLen;
            std::cout << totalSendLen << std::endl;
            //int sel = Select(false, sec, usec);
            //if (sel <= 0)
            //{
            //    return false;
            //}
        }

        return (totalSendLen == len);
    }


    int Socket::Recv(std::string& s, int sec, int usec) const
    {
        char buf[MAXRECV + 1];
        s = "";
        memset(buf, 0, MAXRECV + 1);

        int status = Recv(buf, MAXRECV, sec, usec);
        if (status > 0)
        {
            s += buf;
        }
        else
        {
            return status;
        }

        return static_cast<int>(s.size());
    }


    int Socket::Recv(char* buf, int len, int sec, int usec) const
    {
        if (buf == NULL)
        {
            return -1;
        }

        int select = Select(true, sec, usec);
#ifdef _DEBUG
        if (select == SOCKET_ERROR)
        {
            GetLastError();
        }
#endif
        if (select <= 0)
        {
            return select;
        }

        memset(buf, 0, len);
        int status = ::recv(mSock, buf, len, 0);
#ifdef _DEBUG
        if (status == SOCKET_ERROR)
        {
            GetLastError();
        }
#endif
        return status;
    }


    bool Socket::Connect(const std::string host, const int port)
    {
        if (!IsValid())
        {
            return false;
        }

        mAddr.sin_family = AF_INET;
        mAddr.sin_port = htons(port);
#ifdef WIN32
        mAddr.sin_addr.s_addr = inet_addr(host.c_str());
        if (mAddr.sin_addr.s_addr == INADDR_NONE)
        {
            return false;
        }
#else
        int changestatus = inet_pton(AF_INET, host.c_str(), &mAddr.sin_addr);
        if (changestatus < 0 && errno == EAFNOSUPPORT)
        {
            return false;
        }
#endif

        int status = ::connect(mSock, (sockaddr*)&mAddr, sizeof(mAddr));

#ifdef _DEBUG
        if (status == SOCKET_ERROR)
        {
            GetLastError();
        }
#endif
/*
        if (status != SOCKET_ERROR)
        {
            linger m_sLinger;
            m_sLinger.l_onoff = 1;
            m_sLinger.l_linger = 0;
            status = ::setsockopt(mSock, SOL_SOCKET, SO_LINGER,
                (const char*)&m_sLinger, sizeof(linger));
        }
//*/
        return (status != SOCKET_ERROR);
    }


    void Socket::SetNonBlocking(const bool b)
    {
#ifdef _WIN32
        u_long opts = b ? 1 : 0;
        ioctlsocket(mSock, FIONBIO, &opts);
#else
        int opts = fcntl(mSock, F_GETFL);
        if (opts < 0)
        {
            return;
        }

        opts = b ? (opts | O_NONBLOCK) : (opts & ~O_NONBLOCK);
        fcntl(mSock, F_SETFL,opts);
#endif

    }


    bool Socket::IsValid() const
    {
        return (mSock != INVALID_SOCKET);
    }


    // protected

    int Socket::Select(bool read, long sec, long usec) const
    {
        timeval timeout;
        timeout.tv_sec = sec;
        timeout.tv_usec = usec;
        timeval* tv = ((sec < 0) || (usec < 0)) ? NULL : &timeout;

        fd_set fds;
        FD_ZERO(&fds);
        FD_SET(mSock, &fds);

        int error = 0;
        if (read)
        {  
            error = ::select(1, &fds, 0, 0, tv);
        }
        else
        {
            error = ::select(1, 0, &fds, 0, tv);
        }
#ifdef _DEBUG
        if (error == SOCKET_ERROR)
        {
            GetLastError();
        }
#endif
        return error;
    }


    void Socket::GetLastError()
    {
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4996)
        int err = ::WSAGetLastError();
        TCHAR buf[10];
        swprintf(buf, L"%d: ", err);
        ::OutputDebugString(buf);
#pragma warning(pop)
#endif
    }

}

原创粉丝点击