⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transfersocket_hawk.cpp

📁 电脑编程技巧和源码。很不错的。
💻 CPP
字号:
// TransferSocket_hawk.cpp : implementation file
//

#include "stdafx.h"
#include "TransferSocket_hawk.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTransferSocket_hawk

CTransferSocket_hawk::CTransferSocket_hawk()
{
    m_nSendOffset=0;

    m_bGetRecvSize=FALSE;
    m_nRecvSizeOffset=0;
    m_bGetRecvBeginTag=FALSE;
    m_nRecvBeginTagOffset=0;
    m_pRecvBuf=NULL;
}

CTransferSocket_hawk::~CTransferSocket_hawk()
{
    Close();
}


// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CTransferSocket_hawk, CAsyncSocket)
	//{{AFX_MSG_MAP(CTransferSocket_hawk)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif	// 0

/////////////////////////////////////////////////////////////////////////////
// CTransferSocket_hawk member functions

BOOL CTransferSocket_hawk::Create(UINT nSocketPort,LPCTSTR lpszSocketAddress)
{
    //总是"流"类型的SOCKET
    return CAsyncSocket::Create(
        nSocketPort,
        SOCK_STREAM,
        FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
        lpszSocketAddress);
}

BOOL CTransferSocket_hawk::TransferData(const void *pData,long size)
{
    if (m_hSocket != INVALID_SOCKET)
    {
        //加入长度和"开始"标记
        BYTE *buf=new BYTE [sizeof(long)+BEGIN_TAG_LENGTH+size];
        memcpy(buf,&size,sizeof(long));
        memcpy(buf+sizeof(long),BEGIN_TAG,BEGIN_TAG_LENGTH);
        memcpy(buf+sizeof(long)+BEGIN_TAG_LENGTH,pData,size);
        //如果数据队列为空,则提名FD_WRITE事件,以便执行OnSend来发送数据.
        //如果队列非空,说明有数据正在发送.发送完后,由于队列又加入新数据,
        //还会继续提名FD_WRITE,因此就不需要提名FD_WRITE.
        if (!m_DataQueue.GetSize())
            AsyncSelect();
        m_DataQueue.Add(buf);
        m_DataSizes.Add(sizeof(long)+BEGIN_TAG_LENGTH+size);
        return TRUE;
    }
    else
        return FALSE;
}

int CTransferSocket_hawk::GetQueueCount()
{
    return m_DataQueue.GetSize();
}

void CTransferSocket_hawk::Clear()
{
    //清除跟发送有关的类成员变量
    while (m_DataQueue.GetSize())
    {
        delete [] m_DataQueue[0];
        m_DataQueue.RemoveAt(0);
        m_DataSizes.RemoveAt(0);
    }
    m_nSendOffset=0;

    //清除跟接收有关的类成员变量
    m_bGetRecvSize=FALSE;
    m_nRecvSizeOffset=0;
    m_bGetRecvBeginTag=FALSE;
    m_nRecvBeginTagOffset=0;
    if (m_pRecvBuf)
    {
        delete [] m_pRecvBuf;
        m_pRecvBuf=NULL;
    }
}

void CTransferSocket_hawk::Close()
{
    Clear();

    CAsyncSocket::Close();
}

void CTransferSocket_hawk::OnClose(int nErrorCode) 
{
    Close();
    OnTransferClose(NORMAL);
	
	CAsyncSocket::OnClose(nErrorCode);
}

void CTransferSocket_hawk::OnTransferClose(int reason,int nErrorCode)
{
}

void CTransferSocket_hawk::OnSend(int nErrorCode) 
{
    //之所以还要判断SOCKET句柄,是基于以下两个原因:
    //1 如果一个SOCKET同时既发送数据,又接收数据,当出现发送(或接收)
    //  错误后,即使在OnSend(或OnReceive)中关闭了SOCKET,理论上讲系统
    //  也有可能调用OnReceive(或OnSend);
    //2 曾经碰到过在服务器端正常关闭SOCKET后,客户端先调用OnClose,
    //  然后又调用了OnSend,在Send时出错(一般是连接复位).如果在
    //  OnClose中关闭SOCKET,即使调用OnSend,也是什么都不做.
    if (m_hSocket != INVALID_SOCKET)
    {
        //当连续发送大量数据时,程序可能会不响应用户的输入,
        //因此需要加入消息循环代码.
        MSG msg;
        if (::PeekMessage(&msg,NULL,0,0,PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }

        //如果数据队列不为空,则发送数据
        if (m_DataQueue.GetSize())
        {
            int nBufLen=min(4096,m_DataSizes[0]-m_nSendOffset);
            int result=Send(m_DataQueue[0]+m_nSendOffset,nBufLen);
            if (result == SOCKET_ERROR)
            {
                int err=GetLastError();
                //如果不是阻塞引起的错误,则关闭SOCKET,
                //并调用OnTransferClose.
                //如果是阻塞引起的错误,系统会自己产生一次FD_WRITE事件,
                //可以继续发送数据.
                if (err != WSAEWOULDBLOCK)
                {
                    Close();
                    OnTransferClose(SENDERR,err);
                }
            }
            else
            {
                m_nSendOffset+=result;
                //判断该数据块是否已传送完毕
                if (m_nSendOffset == m_DataSizes[0])
                {   //传送完毕,则删除该数据块
                    delete [] m_DataQueue[0];
                    m_DataQueue.RemoveAt(0);
                    m_DataSizes.RemoveAt(0);
                    m_nSendOffset=0;
                    //如果队列非空,提名FD_WRITE,准备传送下一个数据
                    if (m_DataQueue.GetSize())
                        AsyncSelect();
                    //调用虚函数OnOneDataSent,用户可根据需要重载该函数.
                    //注意:用户有可能在OnOneDataSent()的执行过程中,
                    //     调用TransferData()
                    OnOneDataSent();
                }
                else
                    //没传送完毕,则继续提名FD_WRITE
                    AsyncSelect();
            }
        }
    }
	
	CAsyncSocket::OnSend(nErrorCode);
}

void CTransferSocket_hawk::OnReceive(int nErrorCode) 
{
    //之所以还要判断SOCKET句柄,是基于以下两个原因:
    //1 如果一个SOCKET同时既发送数据,又接收数据,当出现发送(或接收)
    //  错误后,即使在OnSend(或OnReceive)中关闭了SOCKET,理论上讲系统
    //  也有可能调用OnReceive(或OnSend);
    //2 曾经碰到过在服务器端正常关闭SOCKET后,客户端先调用OnClose,
    //  然后又调用了OnSend,在Send时出错(一般是连接复位),这样的话会
    //  调用两次OnTansferClose().如果在OnClose中关闭SOCKET,即使
    //  调用OnSend,也是什么都不做.
    if (m_hSocket != INVALID_SOCKET)
    {
        //当连续接收大量数据时,程序可能会不响应用户的输入,
        //因此需要加入消息循环代码.
        MSG msg;
        if (::PeekMessage(&msg,NULL,0,0,PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
        
        if (!m_bGetRecvSize)
        {   //如果还没有接收完尺寸,继续接收尺寸数据
            int result=Receive(
                (BYTE *)&m_nRecvSize+m_nRecvSizeOffset,
                sizeof(long)-m_nRecvSizeOffset);
            if (result == SOCKET_ERROR)
            {
                int err=GetLastError();
                //如果不是阻塞引起的错误,则调用OnTransferClose,
                //并关闭连接.
                if (err != WSAEWOULDBLOCK)
                {
                    Close();
                    OnTransferClose(RECVERR,err);
                }
            }
            else
            {
                m_nRecvSizeOffset+=result;
                //如果已收到数据块尺寸,准备接收"起始"标记
                if (m_nRecvSizeOffset == sizeof(long))
                {
                    m_bGetRecvSize=TRUE;
                    m_nRecvSizeOffset=0;
                }
            }
        }
        else
        {   //已经得到数据块尺寸
            if (!m_bGetRecvBeginTag)
            {   //如果没有接收完"起始"标记,继续接收
                int result=Receive(
                    m_szRecvBeginTag+m_nRecvBeginTagOffset,
                    BEGIN_TAG_LENGTH-m_nRecvBeginTagOffset);
                if (result == SOCKET_ERROR)
                {
                    int err=GetLastError();
                    //如果不是阻塞引起的错误,则调用OnTransferClose,
                    //并关闭连接.
                    if (err != WSAEWOULDBLOCK)
                    {
                        Close();
                        OnTransferClose(RECVERR,err);
                    }
                }
                else
                {
                    m_nRecvBeginTagOffset+=result;
                    if (m_nRecvBeginTagOffset == BEGIN_TAG_LENGTH)
                    {   //如果已收到"起始"标记,判断是否正确.
                        if (memcmp(m_szRecvBeginTag,BEGIN_TAG,BEGIN_TAG_LENGTH) == 0)
                        {
                            //如果"起始"标记正确,分配接收缓存区,
                            //准备接收数据正文
                            m_bGetRecvBeginTag=TRUE;
                            m_nRecvBeginTagOffset=0;

                            m_pRecvBuf=new BYTE [m_nRecvSize];
                            m_nRecvOffset=0;
                        }
                        else
                        {   //如果"起始"标记错误,调用OnTransferClose,
                            //并关闭连接
                            Close();
                            OnTransferClose(RECVBEGINTAGERR);
                        }
                    }
                }
            }
            else
            {   //数据块尺寸和"起始"标记都已正确接收,开始接收数据正文
                int nBufLen=min(4096,m_nRecvSize-m_nRecvOffset);
                int result=Receive(m_pRecvBuf+m_nRecvOffset,nBufLen);
                if (result == SOCKET_ERROR)
                {
                    int err=GetLastError();
                    //如果不是阻塞引起的错误,则调用OnTransferClose
                    if (err != WSAEWOULDBLOCK)
                    {
                        Close();
                        OnTransferClose(RECVERR,err);
                    }
                }
                else
                {
                    m_nRecvOffset+=result;
                    //如果数据块接收完毕,则准备接收下一个数据块
                    if (m_nRecvOffset == m_nRecvSize)
                    {
                        //调用虚函数OnOneDataReceived.
                        //注意:用户在重载该函数时,需要把数据备份下来.
                        //     因为执行完该函数,收到的数据将被丢弃
                        OnOneDataReceived(m_pRecvBuf,m_nRecvSize);
                        m_bGetRecvSize=FALSE;
                        m_bGetRecvBeginTag=FALSE;
                        delete [] m_pRecvBuf;
                        m_pRecvBuf=NULL;
                    }
                }
            }
        }
    }

	CAsyncSocket::OnReceive(nErrorCode);
}

void CTransferSocket_hawk::OnOneDataSent()
{
}

void CTransferSocket_hawk::OnOneDataReceived(void *pData,long size)
{
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -