使用C中的套接字将文件发送到ftp服务器

amo*_*one 1 c sockets ftp networking

我正在尝试使用套接字将文件上传到我的ftp服务器.它连接到服务器并可以读取目录但不上载文件."STOR"命令在服务器中创建一个空内容的文件.为什么我从服务器获取"无数据连接"响应并且我的文件为空?

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    argv[0]="2";
    argv[1]="ip";

    int sockfd = 0, n = 0;
    char recvBuff[1024];
    struct sockaddr_in serv_addr;
    char mesUser[100]="USER ftpuser\n";
    char mesPass[100]="PASS pass\n";
    char meStor[100]="STOR xx\n";
    char mesPasv[100]="PASV\n";
    char meAppe[100]="APPE xx\n";

    argc=2;

    if(argc != 2)
    {
        printf("\n Usage: %s <ip of server> \n",argv[0]);
        return 1;
    }

    memset(recvBuff, '0',sizeof(recvBuff));
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Error : Could not create socket \n");
        return 1;
    }

    memset(&serv_addr, '0', sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(21);

    if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
     {
     printf("\n inet_pton error occured\n");
     return 1;
     }


    //serv_addr.sin_addr.s_addr = inet_addr(argv[1]);

    if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("\n Error : Connect Failed \n");
        return 1;
    }

    if( send(sockfd , mesUser , strlen(mesUser) , 0) < 0)
    {
        perror("send failed");
        return 1;
    }

    if( send(sockfd , mesPass , strlen(mesPass) , 0) < 0)
    {
        perror("send failed");
        return 1;
    }

    char* fr_name = "pic.jpg";
    FILE *fr = fopen(fr_name, "r");
    if(fr == NULL){
        printf("File cannot be opened");
        return 0;
    }
    else{

        /*if( send(sockfd , mesPasv , strlen(mesPasv) , 0) < 0)
        {
            perror("send failed");
            return 1;
        }*/

        if( send(sockfd , meStor , strlen(meStor) , 0) < 0)
        {
            perror("send failed");
            return 1;
        }



        char buffer[100];
        fscanf(fr,"%s",buffer);
        write(sockfd,buffer,100);


        if( send(sockfd , meAppe , strlen(meAppe) , 0) < 0)
        {
            perror("send failed");
            return 1;
        }
        //close(sockfd);


    }

    /*if( send(sockfd , meStor , strlen(meStor) , 0) < 0)
    {
        perror("send failed");
        return 1;
    }
    */

    while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
    {
        recvBuff[n] = 0;
        if(fputs(recvBuff, stdout) == EOF)
        {
            printf("\n Error : Fputs error\n");
            return 0;
        }
    }

    if(n < 0)
    {
        printf("\n Read error \n");
        return 0;
    } 

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

 220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 6 of 50 allowed.
220-Local time is now 14:41. Server port: 21.
220 You will be disconnected after 15 minutes of inactivity.
331 User username OK. Password required
230 OK. Current restricted directory is /
425 No data connection
425 No data connection
Run Code Online (Sandbox Code Playgroud)

bre*_*s10 6

看起来您对FTP协议的理解不完整.FTP的工作原理是在客户端和服务器之间建立2个套接字连接.第一个是"控制"连接,第二个是"数据"连接.在控件连接上,文本命令来回发送,就像在代码中一样.当需要来回发送数据时,使用数据连接完成.

FTP有两种设置数据连接的方法,如下所述:

  • 活动:客户端指定服务器的端口,服务器连接到客户端计算机上的端口.这很糟糕,因为防火墙和NAT旨在避免这些类型的连接.
  • 被动:服务器为客户端提供连接的端口,客户端连接到服务器计算机上的该端口.

简而言之,您需要:

  1. 使用该PASV命令.
  2. 解析服务器的响应以获取端口号(可能使用scanf).
  3. 打开服务器上该端口的数据连接.
  4. 将您的文件放在该数据连接中.

自从我上次用C语言写套接字以来已经有一段时间了,我没有时间写一个例子,但这应该足以让你开始.(是FTP的规范.RFC就像这样很重读,但它们是明确的,如果你能学会阅读它们,它们可以回答很多问题.)