自己用到了别人写的一套CAsyncSocket类库,基于MFC TCP来实现大文件的传输:服务端主要代码:
 // SendFileServerDlg.cpp : implementation file#include "stdafx.h"
#include "SFServer.h"
#include "SFServerDlg.h"//函数实现文件的发送
DWORD __stdcall SendFileProc(LPVOID lpParameter)
{
...//实现分包发送文件...
        
}
class CAboutDlg : public CDialog
{
public:
CAboutDlg(); enum { IDD = IDD_ABOUTBOX };protected:
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV supportprotected: DECLARE_MESSAGE_MAP()
};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{}void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)END_MESSAGE_MAP()
CSFServerDlg::CSFServerDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSFServerDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_bSending = FALSE;
m_hSendThread = NULL;
m_RequestType = RT_UNKNOWN;
}void CSFServerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_PROGRESS, m_Progress);
DDX_Control(pDX, IDC_FILENAME, m_FileName);}BEGIN_MESSAGE_MAP(CSFServerDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_CHOOSE_FILE, OnChooseFile)
ON_BN_CLICKED(IDC_CANCEL_SEND, OnCancelSend)
ON_BN_CLICKED(IDC_SEND_FILE, OnSendFile)
END_MESSAGE_MAP()BOOL CSFServerDlg::OnInitDialog()
{
CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
} SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
m_ServerSock.SetDialog(this); m_ServerSock.Create(6000, SOCK_STREAM, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, NULL); m_ServerSock.Listen(20);
return TRUE;  // return TRUE  unless you set the focus to a control
}void CSFServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
void CSFServerDlg::OnPaint() 
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}HCURSOR CSFServerDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}void CSFServerDlg::OnOK() 
{}void CSFServerDlg::AcceptConnect()
{
  SOCKADDR_IN pSockAddr;
int pSockAddrLen = sizeof(SOCKADDR_IN); 
//m_ClientSock.ShutDown();
m_ClientSock.Close();
m_ServerSock.Accept(m_ClientSock, (SOCKADDR*)&pSockAddr, &pSockAddrLen);
}void CSFServerDlg::OnReceive()
{
//接收对方发来的应答信息
int nPackageSize = sizeof(CDataPackage);
BYTE* pBuffer = new BYTE[nPackageSize];
int nRecvNum = m_ClientSock.Receive(pBuffer, nPackageSize);
if (nRecvNum >= nPackageSize)
{
CDataPackage* pPackage = (CDataPackage*)pBuffer;
if (pPackage->m_Cmd == SC_CANCEL) //对方取消文件接收
{
m_RequestType = RT_CANCEL;
}
else if (pPackage->m_Cmd == SC_DENY) //对方拒绝接收文件
{
m_RequestType = RT_DENY;
}
else if (pPackage->m_Cmd == SC_ACCEPT) //对方同意接收文件
{
m_RequestType = RT_ACCEPT;
}
}
delete [] pBuffer; //释放缓冲区
}
void CSFServerDlg::OnChooseFile() //选择发送文件
{
CFileDialog flDlg(TRUE, "", "", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
"所有文件|*.*||");
if (flDlg.DoModal()==IDOK)
{
CString szFileName = flDlg.GetPathName();
m_FileName.SetWindowText(szFileName);
}
}void CSFServerDlg::OnCancelSend() 
{
if (m_bSending)
{
//结束发送任务
CDataPackage Package;
Package.m_Type = DP_FILE;
Package.m_Cmd = SC_CANCEL;
Package.m_dwFileSize = 0;
Package.m_dwSize = sizeof(CDataPackage);
Package.m_dwData = 0;
m_ClientSock.Send(&Package, sizeof(CDataPackage));
m_bSending = FALSE;
}
}void CSFServerDlg::OnSendFile() 
{
OnSend();
}void CSFServerDlg::OnSend()
{
throw std::exception("The method or operation is not implemented.");
if (m_bSending)
{
MessageBox("文件发送进行中!");
return;
}
//判断文件是否存在
CString szFileName;
m_FileName.GetWindowText(szFileName); if (!szFileName.IsEmpty())
{
CFileFind flFind;
BOOL bRet = flFind.FindFile(szFileName);
if (bRet)
{

m_szFileName = szFileName;
SendFileProc(this);
}
else
{
MessageBox("文件不存在!");
}
}}

解决方案 »

  1.   

    客户端主要代码:// SFClientDlg.cpp : 实现文件
    //#include "stdafx.h"
    #include "SFClient.h"
    #include "SFClientDlg.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    // 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialog
    {
    public:
    CAboutDlg();// 对话框数据
    enum { IDD = IDD_ABOUTBOX }; protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现
    protected:
    DECLARE_MESSAGE_MAP()
    };CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
    {
    }void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
    CDialog::DoDataExchange(pDX);
    }BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    END_MESSAGE_MAP()
    // CSFClientDlg 对话框
    CSFClientDlg::CSFClientDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CSFClientDlg::IDD, pParent)
    , m_bSending(false)
    {
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_bSending = FALSE;
    m_hGlobal = NULL;
    }void CSFClientDlg::DoDataExchange(CDataExchange* pDX)
    {
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_SERVERIP, m_ServerIP);
    DDX_Control(pDX, IDC_SERVERPORT, m_ServerPort);
    DDX_Control(pDX, IDC_PROGRESS, m_RecvProgress);
    DDX_Control(pDX, IDC_CANCEL_RECV, m_CancelRecv);
    }BEGIN_MESSAGE_MAP(CSFClientDlg, CDialog)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
    ON_BN_CLICKED(IDC_CANCEL_RECV, &CSFClientDlg::OnCancelRecv)
    // ON_BN_CLICKED(IDC_CONNECT, &CSFClientDlg::OnConnect)
    // ON_BN_CLICKED(IDC_CANCEL, &CSFClientDlg::OnCancel)
    ON_BN_CLICKED(IDC_CONNECT, &CSFClientDlg::OnBnClickedConnect)
    ON_BN_CLICKED(IDC_CANCEL, &CSFClientDlg::OnBnClickedCancel)
    END_MESSAGE_MAP()
    // CSFClientDlg 消息处理程序BOOL CSFClientDlg::OnInitDialog()
    {
    CDialog::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
    CString strAboutMenu;
    strAboutMenu.LoadString(IDS_ABOUTBOX);
    if (!strAboutMenu.IsEmpty())
    {
    pSysMenu->AppendMenu(MF_SEPARATOR);
    pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    }
    } // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE); // 设置大图标
    SetIcon(m_hIcon, FALSE); // 设置小图标 //ShowWindow(SW_MAXIMIZE);
    //ShowWindow(SW_MINIMIZE); // TODO: 在此添加额外的初始化代码 m_ClientSock.SetDialog(this); //add by oy at 2012.3.20 return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
    }void CSFClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
    CAboutDlg dlgAbout;
    dlgAbout.DoModal();
    }
    else
    {
    CDialog::OnSysCommand(nID, lParam);
    }
    }// 如果向对话框添加最小化按钮,则需要下面的代码
    //  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
    //  这将由框架自动完成。void CSFClientDlg::OnPaint()
    {
    if (IsIconic())
    {
    CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中
    int cxIcon = GetSystemMetrics(SM_CXICON);
    int cyIcon = GetSystemMetrics(SM_CYICON);
    CRect rect;
    GetClientRect(&rect);
    int x = (rect.Width() - cxIcon + 1) / 2;
    int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标
    dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
    CDialog::OnPaint();
    }
    }//当用户拖动最小化窗口时系统调用此函数取得光标
    //显示。
    HCURSOR CSFClientDlg::OnQueryDragIcon()
    {
    return static_cast<HCURSOR>(m_hIcon);
    }
    void CSFClientDlg::OnReceive()
    {
    //促发接收
    。。
    }
    void CSFClientDlg::RecvFile(CDataPackage *pPackage) //接收文件
    {
    //接收分包的文件
    。。
    }void CSFClientDlg::OnCancelRecv()
    {
    // TODO: 在此添加控件通知处理程序代码
    if(m_bSending)
    {
    CDataPackage package;
    package.m_Type = DP_FILE;
    package.m_Cmd = SC_CANCEL; //取消接收文件
    package.m_dwSize = sizeof(CDataPackage);
    package.m_dwData = 0;
    package.m_dwFileSize = 0;
    m_ClientSock.Send(&package, sizeof(CDataPackage), 0);//发送取消数据包
    }

    }
     
    void CSFClientDlg::OnOK() 
    {}
    void CSFClientDlg::OnBnClickedConnect()
    {
    // TODO: 在此添加控件通知处理程序代码
    // TODO: 在此添加控件通知处理程序代码
    CString szSererIp, szPort;
    m_ServerIP.GetWindowText(szSererIp);
    // MessageBox((char*)LPCTSTR(szSererIp));
    //char *serIp = m_ServerIP.GetBuffer(0);
    m_ServerPort.GetWindowText(szPort); int nPort = atoi(szPort.GetBuffer(0));
    szPort.ReleaseBuffer(0); if(!m_bSending) //当前没有进行文件传输
    {
    m_ClientSock.SetDialog(this);

    BOOL sRet = m_ClientSock.Create();
    if (sRet)
    {
    MessageBox("创建套接字成功");
    }else
    {
    MessageBox("创建套接字失败");
    }

    //m_ClientSock.Connect((char*)LPCTSTR szSererIp, szPort); BOOL bRet = m_ClientSock.Connect((char *)LPCTSTR(szSererIp), nPort);
    MessageBox(szSererIp);
    if(bRet)
    {
    MessageBox("连接成功!", "提示");
    }
    else
    {
    GetLastError();
    MessageBox("连接失败!", "提示");
    }
    //m_ClientSock.SetDialog(this);
    }
    }void CSFClientDlg::OnBnClickedCancel()
    {
    // TODO: 在此添加控件通知处理程序代码
    CDialog::OnCancel();
    }
      

  2.   

    // CQYAsyncSocket 成员函数BOOL CQYAsyncSocket::Accept(CQYAsyncSocket & ConnectedSocket, SOCKADDR * pSockAddr, int * pSockAddrLen) {
    ConnectedSocket.m_bConnected = false;
    ConnectedSocket.m_nSocket = accept( m_nSocket,
    pSockAddr,
    (socklen_t*)pSockAddrLen ); if( -1 == ConnectedSocket.m_nSocket ){
    return FALSE;
    } ConnectedSocket.m_Wnd = CreateWindow( "QYASYNCSOCKET",
    "qyasyncsocket",
    0, 0, 0, 0, 0,
    NULL, NULL, NULL, NULL );
    if( NULL == ConnectedSocket.m_Wnd ){
    goto err;
    } sm_mHandlerTable[ConnectedSocket.m_Wnd] = &ConnectedSocket; if( 0 != WSAAsyncSelect( ConnectedSocket.m_nSocket,
    ConnectedSocket.m_Wnd,
    QY_MSG_SOCKET,
    FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE ) ){
    sm_mHandlerTable.erase( ConnectedSocket.m_Wnd ); goto err;
    }
    ConnectedSocket.m_bConnected = true; ConnectedSocket.OnConnect( 0 );
    return TRUE;err:
    ConnectedSocket.Close();
    return FALSE;
    }BOOL CQYAsyncSocket::Bind(UINT unSocketPort, LPCCH pcSocketAddress) {
    struct sockaddr_in Addr;
    struct hostent* pHost;
    unsigned short usPort = unSocketPort; Addr.sin_family = AF_INET;
    if( NULL == pcSocketAddress || "*" == CString(pcSocketAddress) ){
    Addr.sin_addr.s_addr = INADDR_ANY;
    }
    else {
    pHost = gethostbyname( pcSocketAddress );
    if( NULL == pHost ){
    return FALSE;
    }
    Addr.sin_addr = *( (struct in_addr *)pHost->h_addr );
    } Addr.sin_port = htons( usPort );
    memset( &(Addr.sin_zero), 0, 8 ); if( -1 == bind( m_nSocket,
    (struct sockaddr*)&Addr,
    sizeof( struct sockaddr ) ) ){
    return FALSE;
    } return TRUE;
    }BOOL CQYAsyncSocket::Connect(const PCHAR pcHostAddress, UINT unHostPort) {
    struct sockaddr_in Addr;
    struct hostent* pHost;
    socklen_t AddrLen;
    unsigned short usPort = unHostPort; Addr.sin_family = AF_INET;
    Addr.sin_port = htons( usPort ); Addr.sin_addr.s_addr = inet_addr( pcHostAddress );
    if( Addr.sin_addr.s_addr == INADDR_NONE ){
    pHost = gethostbyname( pcHostAddress ); if( NULL == pHost ){
    return FALSE;
    } Addr.sin_addr = *( (struct in_addr *)pHost->h_addr );
    } memset( &(Addr.sin_zero), 0, 8 ); AddrLen = sizeof( struct sockaddr_in );
    if( -1 == ::connect( m_nSocket,
    (struct sockaddr*)&Addr,
    AddrLen ) ){ m_bConnected = false;
    return FALSE;
    } m_bConnected = true; OnConnect( 0 ); return TRUE;
    }
    void CQYAsyncSocket::Close() {
    if( ( NULL != m_Wnd ) &&
    ( false == sm_mHandlerTable.empty()) &&
    ( sm_mHandlerTable.find( m_Wnd ) != sm_mHandlerTable.end() )  ){
    sm_mHandlerTable.erase( m_Wnd );
    } if( m_nSocket != -1 ){
    ::closesocket( m_nSocket );
    m_nSocket = -1;
    m_bConnected = false;
    }
    }BOOL CQYAsyncSocket::Create(UINT unPort, int nSocketType, long lEvent, LPCTSTR pwcAddress) {
    int nOn = 1;
      
    m_nSocket = socket( AF_INET, nSocketType, 0 );
    if( -1 == m_nSocket ){
        return FALSE;
    }unsigned long nonblocking = 1;
    ioctlsocket( m_nSocket, FIONBIO, (unsigned long*) &nonblocking);/*
    if( fcntl( m_nSocket, F_SETFD, 1 ) == -1) {
        return FALSE;
    }  
    setsockopt( m_nSocket,
                SOL_SOCKET,
                SO_KEEPALIVE,
                (void *)&nOn,
                sizeof(nOn));
    */
      
    if( TRUE == Bind( unPort, pwcAddress ) ){    m_Wnd = CreateWindow( "QYASYNCSOCKEt",
                              "qyasyncsocket",
                              0, 0, 0, 0, 0,
                              NULL, NULL, NULL, NULL );
        if( NULL == m_Wnd ){
            goto err;
        }    sm_mHandlerTable[m_Wnd] = this;
        
        if( 0 != WSAAsyncSelect( m_nSocket,
                                 m_Wnd,
                                 QY_MSG_SOCKET,
                                 lEvent ) ){
            sm_mHandlerTable.erase( m_Wnd );
            goto err;
        }    return TRUE;
    }err:
    Close();
    return FALSE;
    }
    BOOL CQYAsyncSocket::GetSockName(SOCKADDR * SockAddr, int * nSockAddrLen) {
    if( -1 == m_nSocket ){
    return FALSE;
    } if( 0 == getsockname( m_nSocket,
    SockAddr,
    nSockAddrLen ) ){
    return TRUE;
    }
    else{
    return FALSE;
    }}BOOL CQYAsyncSocket::Listen(int nBacklog) {
    if( 0 == listen( m_nSocket, nBacklog )){
    return TRUE;
    } return FALSE;
    }int CQYAsyncSocket::Receive(void* pBuff, int nBuffLen, int nFlags) {
    return ::recv( m_nSocket, (char*)pBuff, nBuffLen, nFlags );
    }
    int CQYAsyncSocket::Send(const void* pBuff, int nBuffLen, int nFlags) {
    return ::send( m_nSocket, (const char*)pBuff, nBuffLen, nFlags );
    }//设置Socket属性.
    BOOL CQYAsyncSocket::SetSockOpt(int nOptionName, const void* pOptionValue, int nOptionLen, int nLevel) {
    if( 0 == setsockopt( m_nSocket,
    nLevel,
    nOptionName,
    (const char*)pOptionValue,
    (socklen_t)nOptionLen ) ){
    return TRUE;
    } return FALSE;
    }void CQYAsyncSocket::init(const HINSTANCE & Inst)
    {
    WSADATA wsa; WSAStartup( MAKEWORD( 2, 2 ), &wsa );  sm_SocketWndClass.style = 0;
    sm_SocketWndClass.lpfnWndProc = CQYAsyncSocket::winProc;
    sm_SocketWndClass.cbClsExtra = 0;
    sm_SocketWndClass.cbWndExtra = 0;
    sm_SocketWndClass.hInstance = Inst;
    sm_SocketWndClass.hIcon = 0;
    sm_SocketWndClass.hCursor = 0;
    sm_SocketWndClass.hbrBackground = 0;
    sm_SocketWndClass.lpszMenuName = 0;
    sm_SocketWndClass.lpszClassName = "QYASYNCSOCKET"; ::RegisterClass( &sm_SocketWndClass );}LRESULT CALLBACK CQYAsyncSocket::winProc(HWND Wnd, unsigned int unMessage, WPARAM Param1, LPARAM Param2)
    {
    switch( unMessage ){
      case QY_MSG_SOCKET:
      {
      int nEvent = WSAGETSELECTEVENT( Param2 );
      int nErrorCode = WSAGETSELECTERROR( Param2 );
      if( true == sm_mHandlerTable.empty() ){
      return 0;
      }
      map< HWND, CQYAsyncSocket* >::iterator itSocket =
      sm_mHandlerTable.find( Wnd );   if( sm_mHandlerTable.end() == itSocket ){
      // 找不到对应的Socket对象,爱莫能助.
      // 这大多数是Socket已经关闭了,这里就只能忽略了.
      return 0;
      }
      if( nEvent & FD_CONNECT ){
      if( NULL == itSocket->second ){
      return 0;
      }
      itSocket->second->OnConnect( nErrorCode );
      }
      if( nEvent & FD_CLOSE ){
      if( NULL == itSocket->second ){
      return 0;
      }
      itSocket->second->OnClose( nErrorCode );
      }
      if( nEvent & FD_ACCEPT ){
      if( NULL == itSocket->second ){
      return 0;
      }
      itSocket->second->OnAccept( nErrorCode );
      }   if( nEvent & FD_READ ){
      if( NULL == itSocket->second ){
      return 0;
      }
      itSocket->second->OnReceive( nErrorCode );
      }   if( nEvent & FD_WRITE ){
      if( NULL == itSocket->second ){
      return 0;
      }
      itSocket->second->OnSend( nErrorCode );
      }   return 0;
      }  default:
      return ::DefWindowProc (Wnd, unMessage, Param1, Param2 );    
    }}void CQYAsyncSocket::OnAccept(int nErrorCode) {}void CQYAsyncSocket::OnClose(int nErrorCode) {}void CQYAsyncSocket::OnReceive(int nErrorCode) {
    }void CQYAsyncSocket::OnSend(int nErrorCode) {
    }void CQYAsyncSocket::OnConnect(int nErrorCode) {
    }WNDCLASS CQYAsyncSocket::sm_SocketWndClass;map< HWND, CQYAsyncSocket * > CQYAsyncSocket::sm_mHandlerTable;