首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

FTP服务器,客户端使用PASV无法连接上解决办法

2012-03-22 
FTP服务器,客户端使用PASV无法连接上头文件rdwr.hC/C++ code#include unistd.h#include errno.h#inclu

FTP服务器,客户端使用PASV无法连接上
头文件rdwr.h

C/C++ code
#include <unistd.h>#include <errno.h>#include <stdio.h>ssize_t readline(int fd, void *vptr, size_t maxlen){    ssize_t n, rc;    char c;    char *ptr;    ptr = vptr;    for (n = 0; n < maxlen; n++) {    again:        if ((rc = read(fd, &c, 1)) == 1) {            *ptr++ = c;            if (c == '\n')                break;        } else if (rc == 0) {            *ptr = 0;            return -1;        } else {            if (errno == EINTR)                goto again;            return -1;        }    }    *ptr = 0;    return n;}ssize_t readn(int fd, void *vptr, size_t n){    size_t nleft;    ssize_t nread;    char *ptr;    ptr = vptr;    nleft = n;    while (nleft > 0) {        if ((nread = read(fd, ptr, nleft)) < 0) {            if (errno == EINTR)                nread = 0;            else                return -1;        } else if (nread == 0) {            break;        }        nleft -= nread;        ptr += nread;    }    return(n - nleft);}ssize_t writen(int fd, void *vptr, size_t n){    size_t nleft;    ssize_t nwritten;    const char *ptr;    ptr = vptr;    nleft = n;    while (nleft > 0) {        if ((nwritten = write(fd, ptr, nleft)) <= 0) {            if (nwritten < 0 && errno == EINTR)                nwritten = 0;            else                return -1;        }        nleft -= nwritten;        ptr += nwritten;    }    return(n - nleft);}ssize_t wr_and_rd(int fd, void *buf, size_t bufsize){    size_t nleft;    ssize_t n;    if (writen(fd, buf, bufsize) < 0)        return -1;    n = read(fd, buf, bufsize);    return n;}

头文件sock.h
C/C++ code
#include <sys/socket.h>#include <sys/types.h>#include <strings.h>#include <netdb.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <stdio.h>#define SA struct sockaddrint create_client_fd(const char *hostname, int port){    int clientfd;    struct hostent *hostinfo;    struct sockaddr_in srv;    struct sockaddr_in cli;    if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)        return -1;    if ((hostinfo = gethostbyname(hostname)) == NULL)        return -2;    bzero(&srv, sizeof(srv));    srv.sin_family = AF_INET;    srv.sin_port = htons(port);    srv.sin_addr = *(struct in_addr *)*hostinfo->h_addr_list;    if (connect(clientfd, (SA *)&srv, sizeof(srv)) < 0) {        close(clientfd);        return -1;    }    return clientfd;}int create_listen_fd(int port, int listen_queue){    int listenfd, optval = 1;    struct sockaddr_in srv;    if ((listenfd = socket(AF_INET, SOCK_STREAM ,0)) < 0)        return -1;    if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,                     (const void *)&optval, sizeof(int)) < 0)        return -1;    bzero(&srv, sizeof(srv));    srv.sin_family = AF_INET;    srv.sin_addr.s_addr = htonl(INADDR_ANY);    srv.sin_port = htons((unsigned short)port);    if (bind(listenfd, (SA *)&srv, sizeof(srv)) < 0)        return -1;    if (listen(listenfd, listen_queue) < 0)        return -1;    return listenfd;}int create_connection(struct sockaddr *srv, size_t srv_len, int port){    int fd;    if ((fd = socket(AF_INET, SOCK_STREAM ,0)) < 0)        return -1;    if (connect(fd, (SA *)&srv, srv_len) < 0)        return -1;    return fd;}

server.h
C/C++ code
int do_login(int fd);int do_current_dir(int fd, int data_fd);int do_show_srv(int fd);int do_show_files(int fd, int data_fd);int do_port_connect(int fd);int do_pasv_connect(int fd);int do_sent_file(int fd, int data_fd);int do_close(int fd); 


server.c
C/C++ code
#include <string.h>#include <unistd.h>#include <fcntl.h>#include "server.h"#include "sock.h"#include "rdwr.h"char cmd_buf[128] = "\0";char cmd_name[128] = "\0";char cmd_arg[128] = "\0";typedef struct {    char *ftp_cmd_name;    int (* ftp_cmd_handler)(int sockfd);} ftpcmd1_s;typedef struct {    char *ftp_cmd_name;    int (* ftp_cmd_handler)(int sockfd, int data_fd);} ftpcmd2_s;ftpcmd1_s ftpcmd1[] = {    {"USER",        do_login},//    {"TYPE",        NULL},    {"SYST",        do_show_srv},//    {"PORT",        do_port_connect},    {"PASV",        do_pasv_connect},//    {"QUIT",        do_close},    {NULL,            NULL},};ftpcmd2_s ftpcmd2[] = {//    {"PWD",            do_current_dir},//    {"LIST",        do_show_files},//    {"STOR",        NULL},    {"RETR",        do_sent_file},//    {"DELE",        NULL},    {NULL,            NULL},};int check_cmd1(){    int i;    for (i = 0; ftpcmd1[i].ftp_cmd_name != NULL; i++) {        if (strcmp(cmd_name, ftpcmd1[i].ftp_cmd_name) == 0) {            return i;        }    }    return -1;}int check_cmd2(){    int i;    for (i = 0; ftpcmd2[i].ftp_cmd_name != NULL; i++) {        if (strcmp(cmd_name, ftpcmd2[i].ftp_cmd_name) == 0) {            return i;        }    }    return -1;}int do_show_srv(clifd){    return talk(clifd, "Linux Fedora 13");}int get_cmd(int sockfd){    int nread;    char *cptr;    bzero(cmd_buf, sizeof(cmd_buf));    bzero(cmd_name, sizeof(cmd_name));    bzero(cmd_arg, sizeof(cmd_arg));    nread = read(sockfd, cmd_buf, sizeof(cmd_buf));    if (nread == -1)        return -1;    if ((cptr = strchr(cmd_buf, '\n')) != NULL)        *cptr = 0;    printf("get cmd: %s\n", cmd_buf);    sscanf(cmd_buf, "%s %s", cmd_name, cmd_arg);    return 0;}int send_cmd(int sockfd, const char *mes){    char buf[1024];    int buflen;    printf("send cmd: %s\n", mes);    if (sprintf(buf, "%s\r\n", mes) < 0)        return -1;    buflen = strlen(buf);    if (writen(sockfd, buf, buflen) != buflen)        return -1;    return 0;}int talk(int sockfd, const char *mes){    if (send_cmd(sockfd, mes) < 0)        return -1;    return get_cmd(sockfd);}int do_login(int clifd){    int nread;    printf("in login\n");    if (strcmp(cmd_name, "USER") != 0) {        talk(clifd, "530 Please Login");    } else if (strcmp(cmd_arg, "red") != 0) {        talk(clifd, "530 username unavailable");    } else {        talk(clifd, "331 Please input password");        if (strcmp(cmd_name, "PASS") != 0) {            talk(clifd, "530 not password");        } else if (strcmp(cmd_arg, "gospursgo") != 0) {            talk(clifd, "530 password error");        } else {            talk(clifd, "230 login succeed");            return 0;        }    }    return -1;}void change_ip(char *ip){    while (*ip++) {        if (*ip == '.') {            *ip = ',';        }    }}int do_pasv_connect(int clifd){    int listenfd, data_fd, addrlen, res, i;    struct sockaddr_in addr;    char local_ip[20], mes[128];    int local_port, net_port;    struct hostent *hostptr;    if ((listenfd = create_listen_fd(8080, 1)) < 0) {        return -1;    }    addrlen = sizeof(struct sockaddr_in);    if (getsockname(clifd, (SA *)&addr, &addrlen) < 0) {        return -1;    }    local_port = 8080;    net_port = htons(local_port);    hostptr = gethostent();    strcpy(local_ip, inet_ntoa(addr.sin_addr));    change_ip(local_ip);//    res = snprintf(mes, sizeof(mes), "227 PORT %s,%d,%d",//        local_ip, local_port / 256, local_port % 256);    res = snprintf(mes, sizeof(mes), "PORT %s,%d,%d",        local_ip, net_port / 256, net_port % 256);    if (res == sizeof(mes) || res < 0)        mes[res] = 0;//    talk(clifd, mes);    send_cmd(clifd, "227");    send_cmd(clifd, mes);    data_fd = accept(listenfd, NULL, NULL);    printf("data_fd = %d\n", data_fd);/*        if ((i = check_cmd2()) < 0) {        talk(clifd, "202 common unavailable");    } else {        ftpcmd2[i].ftp_cmd_handler(clifd, data_fd);    }    close(data_fd);    return 0;*/    return data_fd;}int do_sent_file(int clifd, int data_fd){    char filename[128], buf[1024];    char *ptr;    int res, fd, nread;printf("here\n");    ptr = cmd_arg;    if ((*ptr != '/') && ((*ptr != '.') && (*(ptr + 1) != '/'))) {        res = sprintf(filename, "./%s", cmd_arg);        filename[res] = 0;    }    if ((fd = open(filename, O_RDONLY)) < 0) {        if (access(filename, F_OK) < 0) {            talk(clifd, "450 file not exist");        } else {            talk(clifd, "unable to open the file");        }        return -1;    } else {        talk(clifd, "150 file to sent");        while ((nread = read(fd, buf, sizeof(buf))) > 0) {            writen(data_fd, buf, nread);            writen(STDOUT_FILENO, buf, nread);        }    }    return 0;}int main(){    pid_t listen_pid, clifd, data_fd = -1;    struct sockaddr_in cliaddr;    int clilen, i;    char buf[1024], *cptr;    if ((listen_pid = create_listen_fd(21, 5)) < 0) {        perror("listen");        exit(1);    }    while (1) {        clilen = sizeof(struct sockaddr_in);        clifd = accept(listen_pid, (SA *)&cliaddr, &clilen);        if (clifd < 0) {            perror("accept");        }        talk(clifd, "220 connection succeed, please login");        while (1) {            if ((i = check_cmd1()) >= 0) {                data_fd = ftpcmd1[i].ftp_cmd_handler(clifd);            }            if ((i = check_cmd2()) >= 0) {                ftpcmd2[i].ftp_cmd_handler(clifd, data_fd);            }        }//        close(clifd);    }    exit(0);} 


服务器用户名是red,密码是gospursgo

用linux的ftp命令登陆
ftp 127.0.0.1 21
Connected to 127.0.0.1 (127.0.0.1).
220 connection succeed, please login
Name (127.0.0.1:red): red
331 Please input password
Password:
230 login succeed
ftp> get haha
local: haha remote: haha
227
Passive mode address scan failure. Shouldn't happen!

服务器端显示
send cmd: 220 connection succeed, please login
get cmd: USER red
in login
send cmd: 331 Please input password
get cmd: PASS gospursgo
send cmd: 230 login succeed
get cmd: SYST
send cmd: Linux Fedora 13
get cmd: PASV
send cmd: 227
send cmd: PORT 127,0,0,1,144,31

send cmd是服务器发给客户端的信息,get cmd是服务器接收到的客户端的信息
也就是说,当客户发送PASV后,服务器返回227 PORT

[解决办法]
哪儿是你的客户端代码?
客户端解析127,0,0,1,144,31 错误了吧

你是写服务器代码??
那服务器发送的端口是不是要转换为网络字节序?
[解决办法]
res = snprintf(mes, sizeof(mes), "PORT %s,%d,%d",
local_ip, net_port / 256, net_port % 256);

这附近的问题?
127.0.0.1 ?
尝试用公网IP呢?

热点排行