美文网首页上嵌学习笔记
ftp协议的socket编程简单实现

ftp协议的socket编程简单实现

作者: b6aed1af4328 | 来源:发表于2017-02-20 22:50 被阅读258次

    以linux为例,使用socket编程中的read()函数和write()函数已可实现文件的发送接收,为啥还要专门建立ftp协议呢?单单使用read()函数和write()函数,数据接口和命令接口未分开,效率低。而ftp将数据接口和命令接口分开,提高了文件传输效率和安全性。
    ftp协议的实现仍是使用socket编程,首先是实现tcp连接。
    Socket 客户端编程主要步骤如下:

    • socket() 创建一个 Socket
    • connect() 与服务器连接
    • write() 和 read() 进行会话
    • close() 关闭 Socket

    Socket 服务器端编程主要步骤如下:

    • socket() 创建一个 Socket
    • bind()
    • listen() 监听
    • accept() 接收连接的请求
    • write() 和 read() 进行会话
    • close() 关闭 Socket
      建立tcp连接代码简示如下:
    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);
    

    ftp客户端与服务器建立起tcp连接后,然后向服务器发送命令。(这一步建立的是命令接口的tcp连接,数据接口连接尚未建立。)
    通常第一步发送USER和PASS命令验证账号和密码后登陆服务器。若是匿名服务器则另当别论。
    登陆服务器代码简示如下:

    /* 命令 ”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);
    

    接下来是选择发送PORT命令选择主动模式还是发送PASV命令选择被动模式。
    主动模式还是被动模式是相对服务器来说的。被动模式即命令接口连接和数据接口连接都由客户端主动建立;主动模式是数据接口连接由服务器主动建立。这里仅简述被动模式的建立,主动模式可依理建立。
    被动模式建立连接代码:

    /* 命令 ”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);
    

    客户端发送PASV命令让服务器进入被动模式。服务器会打开数据端口并监听。并返回响应码 227 和数据连接的端口号。
    接下来通过数据端口下载上传查看文件就不赘述了。

    /* 连接服务器新开的数据端口 */
    connect(data_sock,(struct sockaddr *)&server, sizeof(server));
    /* 命令 ”CWD dirname\r\n” */
    sprintf(send_buf,"CWD %s\r\n", dirname);
    /* 客户端发送命令改变工作目录 */
    write(control_sock, send_buf, strlen(send_buf));
    /* 客户端接收服务器的响应码和信息,正常为 ”250 Command okay.” */
    read(control_sock, read_buf, read_len);
    /* 命令 ”SIZE filename\r\n” */
    sprintf(send_buf,"SIZE %s\r\n",filename);
    /* 客户端发送命令从服务器端得到下载文件的大小 */
    write(control_sock, send_buf, strlen(send_buf));
    /* 客户端接收服务器的响应码和信息,正常为 ”213 <size>” */
    read(control_sock, read_buf, read_len);
    /* 命令 ”RETR filename\r\n” */
    sprintf(send_buf,"RETR %s\r\n",filename);
    /* 客户端发送命令从服务器端下载文件 */
    write(control_sock, send_buf, strlen(send_buf));
    /* 客户端接收服务器的响应码和信息,正常为 ”150 Opening data connection.” */
    read(control_sock, read_buf, read_len);
    /* 客户端创建文件 */
    file_handle = open(disk_name, CRFLAGS, RWXALL);
    for( ; ; ) {
    ... ...
    /* 客户端通过数据连接 从服务器接收文件内容 */
    read(data_sock, read_buf, read_len);
    /* 客户端写文件 */
    write(file_handle, read_buf, read_len);
    ... ... 
    }
    /* 客户端关闭文件 */
    rc = close(file_handle);
    

    下载完成后客户端退出服务器,关闭连接。

    /* 客户端关闭数据连接 */
    close(data_sock);
    /* 客户端接收服务器的响应码和信息,正常为 ”226 Transfer complete.” */
    read(control_sock, read_buf, read_len);
    /* 命令 ”QUIT\r\n” */
    sprintf(send_buf,"QUIT\r\n");
    /* 客户端将断开与服务器端的连接 */
    write(control_sock, send_buf, strlen(send_buf));
    /* 客户端接收服务器的响应码,正常为 ”200 Closes connection.” */
    read(control_sock, read_buf, read_len);
    /* 客户端关闭控制连接 */
    close(control_sock);
    

    断点续传的实现
    由于网络不稳定,在传输文件的过程中,可能会发生连接断开的情况,这时候需要客户端支持断点续传的功能,下次能够从上次终止的地方开始接着传送。需要使用命令 REST。如果在断开连接前,一个文件已经传输了 512 个字节。则断点续传开始的位置为 512,服务器会跳过传输文件的前 512 字节。
    ps:响应码啊响应码。
    非常简单的简述,以后再加。

    相关文章

      网友评论

      本文标题:ftp协议的socket编程简单实现

      本文链接:https://www.haomeiwen.com/subject/suaewttx.html