转载自:http://www.ibm.com/developerworks/cn/linux/l-cn-socketftp/index.html#FTP
这是我自己写的客户端程序:http://download.csdn.net/detail/sphone89/4060069
Socket 客户端编程主要步骤如下:
1、socket() 创建一个 Socket
2、connect() 与服务器连接
3、write() 和 read() 进行会话
4、close() 关闭 Socket
Socket 服务器端编程主要步骤如下:
- socket() 创建一个 Socket
- bind()
- listen() 监听
- accept() 接收连接的请求
- write() 和 read() 进行会话
- close() 关闭 Socket
1、客户端和 FTP 服务器建立 Socket 连接。
2、向服务器发送 USER、PASS 命令登录 FTP 服务器。
3、使用 PASV 命令得到服务器监听的端口号,建立数据连接。
4、使用 RETR/STOR 命令下载/上传文件。
5、在下载完毕后断开数据连接并发送 QUIT 命令退出。
当客户端与服务器建立连接后,服务器会返回 220 的响应码和一些欢迎信息。
清单 1. 客户端连接到 FTP 服务器,接收欢迎信息
SOCKET control_sock;
struct hostent *hp;
struct sockaddr_in server;
memset(&server, 0, sizeof(struct sockaddr_in));/* 初始化socket */
control_sock = socket(AF_INET, SOCK_STREAM, 0);
hp = gethostbyname(server_name);
memcpy(&server.sin_addr,
hp->h_addr, hp->h_length);
server.sin_family = AF_INET;
server.sin_port = htons(port);
/* 连接到服务器端 */
connect(control_sock,(struct sockaddr *)&server, sizeof(server));
/* 客户端接收服务器端的一些欢迎信息 */
read(control_sock, read_buf, read_len);
当客户端发送用户名和密码,服务器验证通过后,会返回 230 的响应码。然后客户端就可以向服务器端发送命令了。
图 2. 客户端登录 FTP 服务器
清单 2. 客户端发送用户名和密码,登入 FTP 服务器
/* 命令 ”USER username\r\n” */
sprintf(send_buf,"USER %s\r\n",username);/*客户端发送用户名到服务器端 */
write(control_sock, send_buf, strlen(send_buf))
;/* 客户端接收服务器的响应码和信息,正常为 ”331 User name okay, need password.” */
read(control_sock, read_buf, read_len);
/* 命令 ”PASS password\r\n” */
sprintf(send_buf,"PASS %s\r\n",password);
/* 客户端发送密码到服务器端 */
write(control_sock, send_buf, strlen(send_buf));
/* 客户端接收服务器的响应码和信息,正常为 ”230 User logged in, proceed.” */
read(control_sock, read_buf, read_len);
当客户端在下载/上传文件前,要先发送命令让服务器进入被动模式。服务器会打开数据端口并监听。并返回响应码 227 和数据连接的端口号。
清单 3. 让服务器进入被动模式,在数据端口监听
/* 命令 ”PASV\r\n” */
sprintf(send_buf,"PASV\r\n");
/* 客户端告诉服务器用被动模式 */
write(control_sock, send_buf, strlen(send_buf));
/*客户端接收服务器的响应码和新开的端口号,* 正常为 ”227 Entering passive mode (<h1,h2,h3,h4,p1,p2>)” */
read(control_sock, read_buf, read_len);
当客户端发送命令下载文件。服务器会返回响应码 150,并向数据连接发送文件内容。
当客户端下载完毕后,发送命令退出服务器,并关闭连接。服务器会返回响应码 200。
首先,服务器准备就绪后返回 220。客户端接收到服务器端返回的响应码后,相继发送“USER username” 和 “PASS password” 命令登录。随后,服务器返回的响应码为 230 开头,说明客户端已经登入了。这时,客户端发送 PASV 命令让服务器进入被动模式。服务器返回如 “227 Entering Passive Mode (127,0,0,1,13,67)”,客户端从中得到端口号,然后连接到服务器的数据端口。接下来,客户端发送下载命令,服务器会返回响应码 150,并从数据端口发送数据。最后,服务器返回 “226 transfer complete”,表明数据传输完成。
需要注意的是,客户端不要一次发送多条命令,例如我们要打开一个目录并且显示这个目录,我们得发送 CWD dirname,PASV,LIST。在发送完 CWD dirname 之后等待响应代码,然后再发送后面一条。当 PASV 返回之后,我们打开另一个 Socket 连接到相关端口上。然后发送 LIST,返回 125 之后在开始接收数据,最后返回 226 表明完成。
在传输多个文件的过程中,需要注意的是每次新的传输都必须重新使用 PASV 获取新的端口号,接收完数据后应该关闭该数据连接,这样服务器才会返回一个 2XX 成功的响应。然后客户端可以继续下一个文件的传输。
上传文件与下载文件相比,登入验证和切换被动模式都如出一辙,只需要改变发送到服务器端的命令,并通过数据连接发送文件内容。