下面是数据传输的重点-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. spring配置tomcat jdbc pool数据库连接池

    <bean id="sqliteDataSource" class="org.apache.tomcat.jdbc.pool.DataSource" de ...

  2. 计算系数(codevs 1137)

    题目描述 Description 给定一个多项式(ax + by)^k,请求出多项式展开后x^n y^m项的系数. 输入描述 Input Description 共一行,包含 5 个整数,分别为a,b ...

  3. POJ3132 Sum of Different Primes

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3473   Accepted: 2154 Description A pos ...

  4. Python入门--7--元祖:列表的顽固亲戚

    一.创建和访问一个元祖 zheshiyige_yuanzu=(1,2,3,4,5,6) #创建一个元祖 zheshiyige_yuanzu[1] #打印第二个元素 zheshiyige_yuanzu[ ...

  5. 如何使用ftrace

    基本使用 1. 编译内核 ref:http://www.omappedia.org/wiki/Installing_and_Using_Ftrace========================== ...

  6. 基于CI框架的管理系统

    1:ci框架是有入口文件的,前端和后台入口文件(index.php,admin.php):里面修改$application_folder = 'application/home': 2:项目基本都是在 ...

  7. POJ 1991 Turning in Homework(区间DP)

    题目链接 Turning in Homework 考虑区间DP $f[i][j][0]$为只考虑区间$[i, j]$且最后在$a[i]$位置交作业的答案. $f[i][j][1]$为只考虑区间$[i, ...

  8. codevs科技庄园

    /* 因为每一秒只能走一个单位长度,而每走一个单位长度又会消耗一个体力值,如果体力值没有了时间还有也只能按照体力值计算,反之一样,所以V对于时间和体力值取小 cnt记录有桃子的树的个数,node[cn ...

  9. delphi函数大全

    delphi函数大全Abort                 函数    引起放弃的意外处理Abs                   函数    绝对值函数AddExitProc          ...

  10. websocket笔记

    本文为原创,转载请注明出处: cnzt       文章:cnzt-p http://www.cnblogs.com/zt-blog/p/6742746.html websocket -- 双向通信网 ...