?? datasocket.cpp
字號:
/********************************************************************/
/* */
/* DataSocket.cpp */
/* */
/* Implementation of the Data Socket. */
/* */
/* Programmed by Pablo van der Meer */
/* http://www.pablovandermeer.nl */
/* */
/* Last updated: 29 july 2002 */
/* */
/********************************************************************/
#include "stdafx.h"
#include "resource.h"
#include "DataSocket.h"
#include "ConnectSocket.h"
#include "ConnectThread.h"
#include <afxpriv.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define PACKET_SIZE 4096
/********************************************************************/
/* */
/* Function name : CDataSocket::CDataSocket */
/* Description : Constructor */
/* */
/********************************************************************/
CDataSocket::CDataSocket(CConnectSocket *pSocket, int nTransferType)
{
m_nTransferType = nTransferType;
m_pConnectSocket = pSocket;
m_nStatus = XFERMODE_IDLE;
m_strData = "";
m_File.m_hFile = NULL;
m_bConnected = FALSE;
m_dwRestartOffset = 0;
m_bInitialized = FALSE;
}
/********************************************************************/
/* */
/* Function name : CDataSocket::~CDataSocket */
/* Description : Destructor */
/* */
/********************************************************************/
CDataSocket::~CDataSocket()
{
m_bConnected = FALSE;
TRACE0("CDataSocket destroyed.\n");
}
#if 0
BEGIN_MESSAGE_MAP(CDataSocket, CAsyncSocket)
//{{AFX_MSG_MAP(CDataSocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/********************************************************************/
/* */
/* Function name : CDataSocket::OnSend */
/* Description : Called by the framework to notify socket that */
/* it can send data by calling the Send method. */
/* */
/********************************************************************/
void CDataSocket::OnSend(int nErrorCode)
{
CAsyncSocket::OnSend(nErrorCode);
switch(m_nStatus)
{
case XFERMODE_LIST:
{
while (m_nTotalBytesTransfered < m_nTotalBytesSend)
{
DWORD dwRead;
int dwBytes;
CString strData;
dwRead = m_strData.GetLength();
if (dwRead <= PACKET_SIZE)
{
strData = m_strData;
}
else
{
strData = m_strData.Left(PACKET_SIZE);
dwRead = strData.GetLength();
}
if ((dwBytes = Send(strData, dwRead)) == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK)
{
Sleep(0);
break;
}
else
{
TCHAR szError[256];
wsprintf(szError, "Server Socket failed to send: %d", GetLastError());
// close the data connection.
Close();
m_nTotalBytesSend = 0;
m_nTotalBytesTransfered = 0;
// change status
m_nStatus = XFERMODE_IDLE;
m_pConnectSocket->SendResponse("426 Connection closed; transfer aborted.");
// destroy this socket
AfxGetThread()->PostThreadMessage(WM_THREADMSG, 0, 0);
}
}
else
{
m_nTotalBytesTransfered += dwBytes;
m_strData = m_strData.Mid(dwBytes);
((CConnectThread *)AfxGetThread())->IncSentBytes(dwBytes);
}
}
if (m_nTotalBytesTransfered == m_nTotalBytesSend)
{
// close the data connection.
Close();
m_nTotalBytesSend = 0;
m_nTotalBytesTransfered = 0;
// change status
m_nStatus = XFERMODE_IDLE;
// tell the client the transfer is complete.
m_pConnectSocket->SendResponse("226 Transfer complete");
// destroy this socket
AfxGetThread()->PostThreadMessage(WM_THREADMSG, 0, 0);
}
break;
}
case XFERMODE_SEND:
{
while (m_nTotalBytesTransfered < m_nTotalBytesSend)
{
// allocate space to store data
byte data[PACKET_SIZE];
m_File.Seek(m_nTotalBytesTransfered, CFile::begin);
DWORD dwRead = m_File.Read(data, PACKET_SIZE);
int dwBytes;
if ((dwBytes = Send(data, dwRead)) == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK)
{
Sleep(0);
break;
}
else
{
TCHAR szError[256];
wsprintf(szError, "Server Socket failed to send: %d", GetLastError());
// close file.
m_File.Close();
m_File.m_hFile = NULL;
// close the data connection.
Close();
m_nTotalBytesSend = 0;
m_nTotalBytesTransfered = 0;
// change status
m_nStatus = XFERMODE_IDLE;
m_pConnectSocket->SendResponse("426 Connection closed; transfer aborted.");
// destroy this socket
AfxGetThread()->PostThreadMessage(WM_THREADMSG, 0, 0);
// download failed
((CConnectThread *)AfxGetThread())->UpdateStatistic(FTPSTAT_DOWNLOADFAILED);
}
}
else
{
m_nTotalBytesTransfered += dwBytes;
((CConnectThread *)AfxGetThread())->IncSentBytes(dwBytes);
}
}
if (m_nTotalBytesTransfered == m_nTotalBytesSend)
{
// close file.
m_File.Close();
m_File.m_hFile = NULL;
// close the data connection.
Close();
m_nTotalBytesSend = 0;
m_nTotalBytesTransfered = 0;
// change status
m_nStatus = XFERMODE_IDLE;
// tell the client the transfer is complete.
m_pConnectSocket->SendResponse("226 Transfer complete");
// destroy this socket
AfxGetThread()->PostThreadMessage(WM_THREADMSG, 0, 0);
// download successfull
((CConnectThread *)AfxGetThread())->UpdateStatistic(FTPSTAT_DOWNLOADSUCCEEDED);
}
break;
}
// default:
// break;
}
}
/********************************************************************/
/* */
/* Function name : CDataSocket::OnConnect */
/* Description : Called by the framework to notify connecting */
/* socket that its connection attempt is completed */
/* */
/********************************************************************/
void CDataSocket::OnConnect(int nErrorCode)
{
if (nErrorCode)
m_nStatus = XFERMODE_ERROR;
m_pConnectSocket->SendResponse("425 Can't open data connection.");
// destroy this socket
AfxGetThread()->PostThreadMessage(WM_THREADMSG, 0, 0);
}
else
{
switch (m_nTransferType)
{
case 0: // List Directory
m_nStatus = XFERMODE_LIST;
m_bConnected = TRUE;
OnSend(0);
break;
case 1: // Send File
if (PrepareSendFile(m_strData))
{
m_nStatus = XFERMODE_SEND;
m_bConnected = TRUE;
}
else
{
Close();
}
break;
case 2: // Receive File
if (PrepareReceiveFile(m_strData))
{
m_nStatus = XFERMODE_RECEIVE;
m_bConnected = TRUE;
}
else
{
Close();
m_pConnectSocket->SendResponse("450 can't access file.");
// destroy this socket
AfxGetThread()->PostThreadMessage(WM_THREADMSG, 0, 0);
// upload failed
((CConnectThread *)AfxGetThread())->UpdateStatistic(FTPSTAT_UPLOADFAILED);
}
break;
}
}
CAsyncSocket::OnConnect(nErrorCode);
}
/********************************************************************/
/* */
/* Function name : CDataSocket::OnClose */
/* Description : Called by the framework to notify this socket */
/* that the connected socket is closed. */
/* */
/********************************************************************/
void CDataSocket::OnClose(int nErrorCode)
{
TRACE0("CDataSocket() OnClose()\n");
if (m_pConnectSocket)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -