ftp客户端

本文介绍了FTP数据结构,包括二进制结构、文件式结构和页面结构,并详细讲解了FTP的数据传输模式,如二进制模式、文件模式和压缩模式。在与服务器的连接部分,阐述了FTP使用端口21和20的功能,以及PORT主动模式和PASV被动模式的工作原理。此外,列举了FTP客户端常用的命令,如open、send、get、cd等。在编程实现中,提到了自定义发送命令函数MySockSend()需要注意的问题,特别是在VS2012 + Win7环境下,使用char类型处理网络传输的响应值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、FTP数据结构

  二进制结构:文件中没有内部结构,一般被看作二进制流;

  文件式结构:由许多记录组成的文件;

  页面结构:由不同的索引页组成文件;


二、FTP数据传输模式

 二进制模式:

     在二进制结构中,发送方发送完数据后,会在关闭连接时标记EOF。

 文件模式:

     文件模式就是以文件结构的形式进行数据传输。

 压缩模式:


三、与服务器的连接

FTP在与服务器连接时,需要用到二个端口:

     端口21(FTP默认端口为21)作为控制连接端口,用于发送命令给服务器以及等待服务器响应;

     端口20(任意有效端口号)作为数据传输端口,用来建立数据传输通道;


FYP客户端连接服务器有两种模式:

     PORT模式:PORT为主动模式。需要向服务器提供一个IP地址和一个端口号

     PASV模式: PASV为被动模式。服务器需要提供给客户一个IP地址和一个端口号


FTP常用命令:

        1. open: 与服务器相连接;
  2. send / put:上传文件;
  3. get: 下载文件;
  4. mget: 下载多个文件;
  5. cd: 切换目录;
  6. dir: 查看当前目录下的文件;
  7. del: 删除文件;
  8. bye / exit 退出

参考连接:http://blog.csdn.net/cv_yuippe/article/details/25319533


-------------------------------------------------------------------------



在编程中自定义几个封装函数:

发送命令函数MySockSend()

void CFTP_clientDlg::MySockSend(CString send_msg)
{
	int sign = sock_client.Send(send_msg, send_msg.GetLength());

	if ( SOCKET_ERROR == sign)
	{
		AfxMessageBox("数据发送失败");
		return;
	}

	//将命令添加到ListBox上
    CString show_msg = "命令:";
	show_msg += send_msg;

	m_listinfo.AddString(show_msg);
}


接收响应函数MySockRecv()

void CFTP_clientDlg::MySockRecv()
{
	char buf_recv[128] = "";
	
	int sign = sock_client.Receive(buf_recv,127);

	if(SOCKET_ERROR == sign)
	{
		AfxMessageBox("数据接收失败!");
		return;
	}

	//将信息显示在ListBox上
	
	CString show_msg = "响应: ";
	show_msg += buf_recv;
	memset(buf_recv, strlen(buf_recv), NULL);

	m_listinfo.AddString(show_msg);
}

被动模式PASV函数Pasv_mode()

BOOL CFTP_clientDlg::Pasv_mode()
{
	//创建新的socket
	if ( !sock_temp.Create() )
	{
		AfxMessageBox("sock_temp创建失败");
		return FALSE;
	}

	CString send_msg; //专用于发送信息

	//让服务器进入被动模式,命令:PASV
	send_msg = "PASV\r\n";
	MySockSend(send_msg);

	//接收信息
	char buf_recv[64] = "";
	if ( SOCKET_ERROR == sock_client.Receive(buf_recv, 64) )
	{
		AfxMessageBox("数据接收失败!");
		sock_temp.Close();
		return FALSE;
	}

	//将响应信息添加到列表框
	CString show_msg = "响应:";
	show_msg += buf_recv;
	m_listinfo.AddString(show_msg);

	//解析返回的信息
	CString parse_str = buf_recv;
	int index_first = 0, index_mid = 0, index_end = 0;

	//定义所需信息的位置
	index_end = parse_str.Find(')');
	index_mid = parse_str.ReverseFind(',');
	index_first = parse_str.Find(',', index_mid - 4);

	//获得端口号
	char port_str[4] = "";
	int i,j=0;
	for (i = index_first + 1; i < index_mid; i++)
	{
		port_str[j++] = parse_str.GetAt(i);
	}
	int port_int = atoi(port_str);

	j = 0;
	memset(port_str, 0, 4);


	for (i = index_mid + 1; i < index_end; i++)
	{
		port_str[j++] = parse_str.GetAt(i);
	}

	//计算得出新开的端口号
	port_int = port_int*256 + atoi(port_str);


	//用新的sock连接服务器
	if ( !sock_temp.Connect(m_host, port_int) )
	{
		AfxMessageBox("sock_temp连接服务器失败");
		sock_temp.Close();
		return FALSE;
	}

	return TRUE;
}

解析函数Parse_list()

void CFTP_clientDlg::Parse_list()
{
	//用新的socket接收文件信息
	char filelist[1024] = "";
	if ( SOCKET_ERROR == sock_temp.Receive(filelist, 1024) )
	{
		AfxMessageBox("数据接收失败");
		return;
	}

	CString parselist = filelist;

	//获取字符串的长度
	long len = parselist.GetLength();

	//解析获取所有的文件名
	char filename[32] = "";
	int index_rn = parselist.Find("\r\n");  //第一行信息结束的位置
	int i,j=0;

	while ( len - 1 != index_rn + 1)  //获取的长度不等于第一个"\r\n"则去查找
	{
		//获取文件名的起始位置
		for ( i = index_rn - 1; parselist.GetAt(i) != ' '; i--);

		//获取文件名
		for (i = i + 1; i < index_rn; i++)
		{
			filename[j++] = parselist.GetAt(i);
		}
		j = 0;

		//找到下一行结束的位置
		index_rn = parselist.Find("\r\n", index_rn + 2);
		
		//忽略"."和".."文件
		if ( filename[0] == '.' )
		{
			memset(filename, 0, 32);
			continue;
		}

		//将文件名添加到文件列表框中
		m_listfile.AddString(filename);
		memset(filename, 0, 32);
	}

	//获取最后一个文件名
	//获取文件名起始位置
	for ( i = index_rn - 1; parselist.GetAt(i) != ' '; i--);

	for (i = i + 1; i < index_rn; i++)
	{
		filename[j++] = parselist.GetAt(i);
	}
	if (filename[0] == '.')
	{
		return;
	}

	m_listfile.AddString(filename);
}

总结:

IDE:vs2012 + win7,在返回的响应值由char类型保存,如果用wchar则会出现乱码,这是因为在网络传输中还是以单字节为主。

本实例源代码


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值