VC FTP服务器程序分析(四)
下面是数据传输的重点-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服务器程序分析(四)的更多相关文章
- VC FTP服务器程序分析(一)
想在QT上移植一个FTP服务器程序,先学习windows下的FTP服务器例子,然后随便动手写点东西. 在pudn上搜索 "FTP服务器端和客户端实现 VC“这几个关键字,就可以搜到下面要分析 ...
- VC FTP服务器程序分析(二)
上面讲到了CClientThread类,打开这个类的实现,这个类实现了4个函数.依次分析: 1.InitInstance 其说明如下:InitInstance必须被重载以初始化每个用户界面线程的新 ...
- VC FTP服务器程序分析(三)
CControlSocket类的分析,CControlSocket类的内容比较多,为什么呢.因为通信控制命令的传输全部在这里,通信协议的多样也导致了协议解析的多样. 1.OnReceive 其大致说 ...
- 搭建ftp服务器实现文件共享
FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务. FTP(File Transfer Protocol ...
- 转:【专题十二】实现一个简单的FTP服务器
引言: 休息一个国庆节后好久没有更新文章了,主要是刚开始休息完心态还没有调整过来的, 现在差不多进入状态了, 所以继续和大家分享下网络编程的知识,在本专题中将和大家分享如何自己实现一个简单的FTP服务 ...
- Linux中搭建FTP服务器
FTP工作原理 (1)FTP使用端口 [root@localhost ~]# cat /etc/services | grep ftp ftp-data 20/tcp #数据链路:端口20 ftp 2 ...
- 专题十二:实现一个简单的FTP服务器
引言: 在本专题中将和大家分享如何自己实现一个简单的FTP服务器.在我们平时的上网过程中,一般都是使用FTP的客户端来对商家提供的服务器进行访问(上传.下载文件),例如我们经常用到微软的SkyDriv ...
- centos yum安装与配置vsFTPd FTP服务器(转)
vsftpd作为FTP服务器,在Linux系统中是非常常用的.下面我们介绍如何在centos系统上安装vsftp. 什么是vsftpd vsftpd是一款在Linux发行版中最受推崇的FTP服务器程序 ...
- [CentOs7]搭建ftp服务器
摘要 vsftpd 是“very secure FTP daemon”的缩写,安全性是它的一个最大的特点.vsftpd 是一个 UNIX 类操作系统上运行的服务器的名字,它可以运行在诸如 Linux. ...
随机推荐
- XPosed框架_简单的应用
0. Xposed框架简介 关于Xposed框架相信大家应该不陌生了,他是Android中Hook技术的一个著名的框架,而Xposed框架是免费的而且还是开源的,本文主要介绍如何通过这个框架来进行系统 ...
- 【单调队列+尺取】HDU 3530 Subsequence
acm.hdu.edu.cn/showproblem.php?pid=3530 [题意] 给定一个长度为n的序列,问这个序列满足最大值和最小值的差在[m,k]的范围内的最长子区间是多长? [思路] 对 ...
- 洛谷P3393 逃离僵尸岛
题目描述 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被僵尸控制了,如果贸然闯入 ...
- Peaks BZOJ 3545 / Peaks加强版 BZOJ 3551
Peaks [问题描述] 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问 ...
- 查看mysql库中所有表的大小和记录数
查看mysql库中所有表的大小和记录数 ,), 'MB') as total_size FROM information_schema.TABLES WHERE TABLE_SCHEMA='datab ...
- 有向图tarjan算法求连通分量的粗浅讲解、证明, // hdu1269
打算开始重新复习一遍相关算法.对于有向图tarjan算法,通过学习过很多说法,结合自己的理解,下面给出算法自己的观点. 算法总模型是一个dfs,结合一个stack(存放当前尚未形成SCC的点集合),记 ...
- RabbitMQ核心组件及应用场景
一.适用场景 1.解耦 2.最终一致性 3.广播 4.错峰与流控(秒杀业务用于流量削峰场景) 秒杀场景 二.核心组件,关键点(交换器.队列.绑定) AMPQ消息路由必要三部分:交换器.队列.绑定. J ...
- Ryuji doesn't want to study (树状数组)
[传送门]:https://nanti.jisuanke.com/t/31460 [题意]给定一个数组a[N],有两种操作, 操作1,给定 l , r, 查询a[l]×L+a[l+1]×(L−1)+ ...
- android 圆形按钮
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&q ...
- fuel 安装openstack