下面是数据传输的重点-CDataSocket类,函数不多,都比较重要。

  1、OnAccept  数据tcp服务器被连接的虚函数,由框架调用。

 void CDataSocket::OnAccept(int nErrorCode)
{
// Accept the connection using a temp CSocket object.
CAsyncSocket tmpSocket;
Accept(tmpSocket); SOCKET socket = tmpSocket.Detach();
Close(); Attach(socket); m_bConnected = TRUE; CAsyncSocket::OnAccept(nErrorCode);
}

  第7行 得到套接字描述符socket。第8行关闭监听的这个套接字,第11行关联socket与本对象,第12行,标记连接标志。这种处理方法少写一个类。因为tcp监听得一个socket,而连接上来的客户端也需要一个socket来与之通信。这样做适合只有一个客户端的情况。

  2、OnReceive  数据接收处理函数

 int CDataSocket::Receive()
{
TRACE("OnReceive\n");
int nRead = ; if (m_pControlSocket->m_nStatus == STATUS_UPLOAD)
{
if (m_File.m_hFile == NULL)
return ; byte data[PACKET_SIZE];
nRead = CAsyncSocket::Receive(data, PACKET_SIZE); switch(nRead)
{
case :
{
m_File.Close();
m_File.m_hFile = NULL;
Close();
// tell the client the transfer is complete.
m_pControlSocket->SendResponse("226 Transfer complete");
// destroy this socket
AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, , );
break;
}
case SOCKET_ERROR:
{
if (GetLastError() != WSAEWOULDBLOCK)
{
m_File.Close();
m_File.m_hFile = NULL;
Close();
m_pControlSocket->SendResponse("426 Connection closed; transfer aborted.");
// destroy this socket
AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, , );
}
break;
}
default:
{
TRY
{
m_File.Write(data, nRead);
}
CATCH_ALL(e)
{
m_File.Close();
m_File.m_hFile = NULL;
Close();
m_pControlSocket->SendResponse("450 Can't access file.");
// destroy this socket
AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, , );
return ;
}
END_CATCH_ALL;
break;
}
}
}
return nRead;
}

  如果处于上传状态,那么将接收到的数据写入文件。

  3、PreSendFile 与发送文件有关的函数

 BOOL CDataSocket::PrepareSendFile(LPCTSTR lpszFilename)
{
// close file if it's already open
if (m_File.m_hFile != NULL)
{
m_File.Close();
} // open source file
if (!m_File.Open(lpszFilename, CFile::modeRead | CFile::typeBinary))
{
return FALSE;
}
m_nTotalBytesSend = m_File.GetLength(); if (m_pControlSocket->m_dwRestartOffset < m_nTotalBytesSend)
{
m_nTotalBytesTransfered = m_pControlSocket->m_dwRestartOffset;
}
else
{
m_nTotalBytesTransfered = ;
}
return TRUE;
}

 初始化文件描述符m_File,m_nTotalBytesSend,m_nTotalBytesTransfered。

 4、 SendFile函数  调用PrepareSendFile,调用OnSend发送文件。

 void CDataSocket::SendFile(LPCTSTR lpszFilename)
{
if (!PrepareSendFile(lpszFilename))
{
// change status
m_pControlSocket->m_nStatus = STATUS_IDLE; m_pControlSocket->SendResponse("426 Connection closed; transfer aborted."); // destroy this socket
AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, , );
return;
}
OnSend();
}

 5、SendData 发送数据 是为了LIST命令而准备,发送文件目录列表。

 6、OnSend 主要区分了list命令的情况和download的情况。

 void CDataSocket::OnSend(int nErrorCode)
{
CAsyncSocket::OnSend(nErrorCode);
switch(m_pControlSocket->m_nStatus)
{
case STATUS_LIST:
{
while (m_nTotalBytesTransfered < m_nTotalBytesSend)
{
DWORD dwRead;
int dwBytes; CString strDataBlock; dwRead = m_strData.GetLength(); if (dwRead <= PACKET_SIZE)
{
strDataBlock = m_strData;
}
else
{
strDataBlock = m_strData.Left(PACKET_SIZE);
dwRead = strDataBlock.GetLength();
} if ((dwBytes = Send(strDataBlock, dwRead)) == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK)
{
Sleep();
return;
}
else
{
TCHAR szError[];
wsprintf(szError, "Server Socket failed to send: %d", GetLastError()); // close the data connection.
Close(); m_nTotalBytesSend = ;
m_nTotalBytesTransfered = ; // change status
m_pControlSocket->m_nStatus = STATUS_IDLE; m_pControlSocket->SendResponse("426 Connection closed; transfer aborted."); // destroy this socket
AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, , );
}
}
else
{
m_nTotalBytesTransfered += dwBytes;
m_strData = m_strData.Mid(dwBytes);
}
}
if (m_nTotalBytesTransfered == m_nTotalBytesSend)
{
// close the data connection.
Close(); m_nTotalBytesSend = ;
m_nTotalBytesTransfered = ; // change status
m_pControlSocket->m_nStatus = STATUS_IDLE; // tell the client the transfer is complete.
m_pControlSocket->SendResponse("226 Transfer complete");
// destroy this socket
AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, , );
}
break;
}
case STATUS_DOWNLOAD:
{
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();
break;
}
else
{
TCHAR szError[];
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 = ;
m_nTotalBytesTransfered = ; // change status
m_pControlSocket->m_nStatus = STATUS_IDLE; m_pControlSocket->SendResponse("426 Connection closed; transfer aborted."); // destroy this socket
AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, , );
}
}
else
{
m_nTotalBytesTransfered += dwBytes;
}
}
if (m_nTotalBytesTransfered == m_nTotalBytesSend)
{
// close file.
m_File.Close();
m_File.m_hFile = NULL; // close the data connection.
Close(); m_nTotalBytesSend = ;
m_nTotalBytesTransfered = ; // change status
m_pControlSocket->m_nStatus = STATUS_IDLE; // tell the client the transfer is complete.
m_pControlSocket->SendResponse("226 Transfer complete");
// destroy this socket
AfxGetThread()->PostThreadMessage(WM_DESTROYDATACONNECTION, , );
}
break;
}
}
}

  7、OnConnect函数  tcp连接成功时被框架调用的虚函数。

  8、OnClose函数 当数据发送完成或者接收完成后被框架调用的虚函数。主要做清理工作。

  9、

 

VC FTP服务器程序分析(四)的更多相关文章

  1. VC FTP服务器程序分析(一)

    想在QT上移植一个FTP服务器程序,先学习windows下的FTP服务器例子,然后随便动手写点东西. 在pudn上搜索 "FTP服务器端和客户端实现 VC“这几个关键字,就可以搜到下面要分析 ...

  2. VC FTP服务器程序分析(二)

    上面讲到了CClientThread类,打开这个类的实现,这个类实现了4个函数.依次分析: 1.InitInstance   其说明如下:InitInstance必须被重载以初始化每个用户界面线程的新 ...

  3. VC FTP服务器程序分析(三)

    CControlSocket类的分析,CControlSocket类的内容比较多,为什么呢.因为通信控制命令的传输全部在这里,通信协议的多样也导致了协议解析的多样. 1.OnReceive  其大致说 ...

  4. 搭建ftp服务器实现文件共享

    FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务. FTP(File Transfer Protocol ...

  5. 转:【专题十二】实现一个简单的FTP服务器

    引言: 休息一个国庆节后好久没有更新文章了,主要是刚开始休息完心态还没有调整过来的, 现在差不多进入状态了, 所以继续和大家分享下网络编程的知识,在本专题中将和大家分享如何自己实现一个简单的FTP服务 ...

  6. Linux中搭建FTP服务器

    FTP工作原理 (1)FTP使用端口 [root@localhost ~]# cat /etc/services | grep ftp ftp-data 20/tcp #数据链路:端口20 ftp 2 ...

  7. 专题十二:实现一个简单的FTP服务器

    引言: 在本专题中将和大家分享如何自己实现一个简单的FTP服务器.在我们平时的上网过程中,一般都是使用FTP的客户端来对商家提供的服务器进行访问(上传.下载文件),例如我们经常用到微软的SkyDriv ...

  8. centos yum安装与配置vsFTPd FTP服务器(转)

    vsftpd作为FTP服务器,在Linux系统中是非常常用的.下面我们介绍如何在centos系统上安装vsftp. 什么是vsftpd vsftpd是一款在Linux发行版中最受推崇的FTP服务器程序 ...

  9. [CentOs7]搭建ftp服务器

    摘要 vsftpd 是“very secure FTP daemon”的缩写,安全性是它的一个最大的特点.vsftpd 是一个 UNIX 类操作系统上运行的服务器的名字,它可以运行在诸如 Linux. ...

随机推荐

  1. PHP中的验证码类(准备篇)

    <!--code.php内容--> <?php //开启session session_start(); include "vcode.class.php"; / ...

  2. Linux(10):期中架构(2)--- NFS存储服务 & 实时同步

    1. 共享存储服务概念: # NFS是Network File System的缩写,中文意思是网络文件系统, # 它的主要功能是通过网络(一般是局域网)让不同的主机系统之间可以共享文件或目录. 2. ...

  3. POJ2560 Freckles

    Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %lld & %llu Description In an epis ...

  4. 16.1113 模拟考试T3

    城堡[问题描述]给定一张N个点M条边的无向连通图,每条边有边权.我们需要从M条边中选出N − 1条, 构成一棵树. 记原图中从 1 号点到每个节点的最短路径长度为?Di ,树中从 1 号点到每个节点的 ...

  5. Java 模板权重随机

    Template templates=...// 所有的模板 final int _weights=1000; // 所有的模板权重 Template _template=null; //随机一个权重 ...

  6. 洛谷——P2074 危险区域

    P2074 危险区域 题目背景 一个恐怖组织在一座城市中安放了定时炸弹,其威力巨大,现在这里的警长想知道最坏的情况下会有多少街区受威胁. 题目描述 在一个城市有N*M个街区,每个街区由坐标描述,如图所 ...

  7. Windows使用Telnet连接Linux服务器初探(待实践)

    在Windows下可以适用Telnet连接Linux服务器,但是前提是在Linux下需要安装Tlenet-Server.还要开启防火的23端口.搞定之后就可以用telnet IP进行连接. 但是,我发 ...

  8. Unix操作系统LD_PRELOAD简介

    http://blog.csdn.net/ieearth/article/details/49952047 Unix操作系统的动态链接库的知识中,这个功能主要就是用来有选择性的载入Unix操作系统不同 ...

  9. android应用开发之View的大小计量单位(px、dpi、dp、dip、sp)

    http://blog.csdn.net/ljianhui/article/details/43601495?ref=myread 一.像素(px)与屏幕分辨率 1)px(Pixels ,像素):对应 ...

  10. 如何更改ORACLE 用户的 expired状态

    ORACLE(113) 版权声明:本文为博主原创文章,未经博主允许不得转载. oracle中, 经常用户的状态会变成locked, expired 等状态, 这种情况下怎么处理呢? 首先,  如果是l ...