荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: jjk (UNIX+C+XML+?? 傻了?), 信区: Linux
标  题: 一个使用ftp协议的程序片段              guru (转寄)[转载]
发信站: 荔园晨风BBS站 (Thu Apr 25 10:25:39 2002), 转信

【 以下文字转载自 jjk 的信箱 】
【 原文由 jjk.bbs@apue.dhs.org 所发表 】
judite
(stranger)
07/17/01 08:01 PM
  ftp c programming
请问PORT指令怎么用啊,我看了rfc,很简单还没man说的明了呢,
man里说PORT 127,0,0,1,192,0之后server会联接到client的指定端口,
但我用netstat没发现有这样一个联接啊。是不是还需要执行什么指令?谢谢!
astonia
(member)
11/13/00 11:07 AM
我提供一个使用ftp协议的程序片断,已经稳定运行了10个月.
ftpapi.c:
#include <signal.h>
#include <stdarg.h>
#include <errno.h>
#include "ftpapi.h"
#include "rdwr.h"
const response_t response_err = RESPONSE_ERR;
const response_t response_empty = RESPONSE_EMPTY;
int read_line(buf_t *buf,char *buff,int maxlen){
   char ch;
   int n,rc;
   for ( n = 0; n < maxlen; ) {
      if ((rc = read_1_byte(buf,&buff[n])) == 1) {
         if (buff[n++] == '\n') break;
      } else if (!rc) {
         if (n == 0) return (0);
  else break;
      } else return -1;
   }
   buff[n-1] = 0;
   return n;
}
int open_data_channel(ftp_t *ftp_info){
   struct sockaddr_in servaddr;
   int so_reuseaddr = 1;
   size_t servaddr_size = sizeof(servaddr);
   /* socket */
   if ((ftp_info->data_channel_sockfd = socket(AF_INET,SOCK_STREAM,0))< 0)
      return -1;
   /* set reuse address */
    if(setsockopt(ftp_info->data_channel_sockfd,SOL_SOCKET,SO_REUSEADDR,&so_
reuseaddr,sizeof(so_reuseaddr)) < 0) {
      (void) close(ftp_info->data_channel_sockfd);
      return -1;
   }
   /* set servaddr */
   bzero(&servaddr,sizeof(servaddr));
   servaddr.sin_family = AF_INET;
   servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
   /* bind, let kernel choose the port */
   if (bind(ftp_info->data_channel_sockfd,(SA *)&servaddr,servaddr_size)== -
1) {
      (void) close(ftp_info->data_channel_sockfd);
      return -1;
   }
   /* listen to the port as a server*/
   if (listen(ftp_info->data_channel_sockfd,SOMAXCONN) == -1) {
      (void) close(ftp_info->data_channel_sockfd);
      return -1;
   }
   /* get port no choosed by kernel */
   if(getsockname(ftp_info->data_channel_sockfd,(SA*)&servaddr,&servaddr_siz
e) == -1) {
      (void) close(ftp_info->data_channel_sockfd);
      return -1;   }
//**
   ftp_info->data_port = ntohs(servaddr.sin_port);
   return ftp_info->data_channel_sockfd;
/* return socketdescriptor */
}
int ftp_command(ftp_t *ftp_info,const char *fmt,...){
   va_list ap;
   char cmdline[MAXLINESIZE], recvline[MAXLINESIZE];
   int n = 0;
   size_t cmdlen;
   /* form command line */
   va_start(ap,fmt);
   /* reserve the space of \r\n\0 */   vsnprintf(cmdline,sizeof(cmdline)-3,f
mt,ap);
   va_end(ap);
   (void) strcat(cmdline,"\r\n");
   printf(cmdline);
   /* command length */
   cmdlen = strlen(cmdline);
   /* send cmd to ftpd */
   begin_send_cmd:
   if ((n=write(ftp_info->command_channel_sockfd,&cmdline[0]+n,cmdlen)) < 0)
 {
      /* interrupted by signal */
      /*
      if (errno == EINTR) {
         n = 0;
         goto begin_send_cmd;      }
      */
      ftp_info->response = response_err;
      return -1;
/* send cmd to ftpd failed */
   }   if (n < cmdlen) {
            /* send command incompletely */
      cmdlen -= n;
/* resend from the break point */
      goto begin_send_cmd;   }
/* get response */
   get_response(ftp_info);
   return 0;
/* succeed */
}
int connect_to_ftpd(ftp_t *ftp_info,const char *ip,u_short port){   struct s
ockaddr_in servaddr;
   struct hostent *hp;
   int n;
   int errno_save;
   char recvline[MAXLINESIZE];
   size_t servaddr_size = sizeof(servaddr);
   bzero(ftp_info,sizeof(ftp_t));
   ftp_info->server_port = port;
   /* socket command channel */
   if ((ftp_info->command_channel_sockfd=socket(AF_INET,SOCK_STREAM,0)) < 0)
 return -1;
   /* set zero to servaddr */
   bzero(&servaddr,servaddr_size);
   /* set family to AF_INET */
   servaddr.sin_family = AF_INET;
   /* change port to network byte order */
   servaddr.sin_port = htons(port);
   /* get host by name or ip is an IP address presentation */
   if ((hp = gethostbyname(ip)) == NULL) {
/* ip is an IP */
      if ((servaddr.sin_addr.s_addr = inet_addr(ip)) <= 0) {
         errno_save = errno;
         (void) close(ftp_info->command_channel_sockfd);
         errno = errno_save;
         return -1;
      }
   } else {
/* ip is an alias */
      (void)memcpy(&servaddr.sin_addr,hp->h_addr_list[0],sizeof(servaddr.sin
_addr));
   }
/* connect to ftp server command channel */
   if (connect(ftp_info->command_channel_sockfd,(SA*)&servaddr,servaddr_size
) < 0) {
      errno_save = errno;
      (void) close(ftp_info->command_channel_sockfd);
      errno = errno_save;
      return -1;
   }
/* get local ip connect to ftp server */
   if (getsockname(ftp_info->command_channel_sockfd,(SA*)&servaddr,&servaddr
_size) == -1) {
      errno_save = errno;
      (void) close(ftp_info->command_channel_sockfd);
      errno = errno_save;
      return -1;
   }
   ftp_info->local_ip = servaddr.sin_addr.s_addr;
/* get response from ftp server */
   get_response(ftp_info);
   if (ftp_info->response.primary_code != 2) {
      errno_save = errno;
      (void) close(ftp_info->command_channel_sockfd);
      errno = errno_save;
      return -1;
/* fail */
   } else {
      return 0;
/* succeed */
   }
}
void get_response(ftp_t *ftp_info){
   int n;
   buf_t buf;
   /* init buf */
   init_buf(&buf,ftp_info->command_channel_sockfd);
/* get the response message from ftpd */
   n =read_line(&buf,&ftp_info->response_line[0],sizeof(ftp_info->response_l
ine)-1);
   if (n < 0) {
      ftp_info->response = response_err;
      (void) destroy_buf(&buf);
      return;
/* read socket failed */
   }
   if (!n) {
      ftp_info->response = response_empty;
      (void) destroy_buf(&buf);
      return;
/* nothing read, socket closed */
   }printf("%s\n",ftp_info->response_line);
   ftp_info->response.primary_code = ftp_info->response_line[0] - '0';
/* primary code */
   ftp_info->response.return_code = atoi(ftp_info->response_line);
/* get response code */
   if (strlen(ftp_info->response_line) < 4 ||ftp_info->response_line[3] != '
-') {
      (void) destroy_buf(&buf);
      return;
/* single line response */
   }
/* handle multi-line responses */
   while (n) {
/* sth else to read from socket*/
      n =read_line(&buf,&ftp_info->response_line[0],sizeof(ftp_info->respons
e_line)-1);
      if (n < 0) {
         ftp_info->response = response_err;
         (void) destroy_buf(&buf);
         return;
/* read socket failed */
      }printf("%s\n",ftp_info->response_line);
      if (strlen(ftp_info->response_line) > 3 &&ftp_info->response_line[3] =
= ' '
         && ftp_info->response.return_code ==atoi(ftp_info->response_line))
{
         (void) destroy_buf(&buf);
         return;
/* finish reading */
      }
   }
/* should not reach the next line
* because when n == 0, it means the socket is closed by other end
*/
   strcat(ftp_info->response_line,"\n");
   (void) destroy_buf(&buf);
   return;
/* succeed */
}
int close_command_channel(ftp_t *ftp_info){
   return close(ftp_info->command_channel_sockfd);}intclose_data_channel(ftp
_t *ftp_info){
   return close(ftp_info->data_channel_sockfd);
}
ftpapi.h:
#ifndef _CS_FTPAPI_H_
#define _CS_FTPAPI_H_
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
/* ftp server return codes */
#define FTPD_USERUNKOWN         530
/* user unkown */
#define FTPD_READY              220
/* ftp server ready */
#define FTPD_USERFIRST          503
/* login with USER first */
#define FTPD_BYE                221
/* goodbye */
#define FTPD_OK                 200
/* command successful */
#define FTPD_REQPASS            331
/* password required */
#define FTPD_LOGIN              230
/* user logged in */
#define FTPD_PWD                257
/* xx is current directory */
#define FTPD_CWD                250
/* CWD command successful */
#define FTPD_NOENT              550
/* no such file or dir */
#define FTPD_HELP               214
/* HELP message */
#define FTPD_CMDUNKOWN          500
/* command not understood */
#define FTPD_NOTIMPLE           502
/* command not implemented */
#define FTPD_CANTCONN           425
/* can't build data connection*/
#define FTPD_ASCCONN            150
/* data connection for xx */
#define FTPD_TRANCOMP           226
/* transfer complete */
#define FTPD_ABOR               225
/* ABOR command successful */
/* max size of response line */
#define MAXLINESIZE 1024
/* convinience for programming */
#define SA struct sockaddr
/* define the data structure of the ftp server return code */
/* primary_code stores the primary code which indicates the
* primary result from ftp server * return_code is the full 3-digit result
* constant {-1, -1} indicates error occured,
* and {0, 0} indicates empty response(maybe socket closed).
*/
#define RESPONSE_ERR    {-1, -1}














































































--
※ 转寄:·UNIX编程 apue.dhs.org·[FROM: 210.39.3.50]
--
※ 转载:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.0.146]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店