liaoy_jackie 发表于 2008-10-20 14:58

代理tcp服务器如何实现ftp功能?

大家好。
我现在在做一个tcp代理服务器,实现转发的功能。我有3台电脑,分别作为本地客户端,代理服务器以及远程客户端,其中代理服务器上面有2个网卡,一个
是内网的,一个是外网的。
本地客户机的ip:192.168.0.10

代理服务器的ip:
内网的ip:192.168.0.1
外网的ip:202.202.68.191


远程服务器的ip:202.202.68.201


最终就是想在本地客户机192.168.0.10的基础上通过cuteftp 登陆到远程主机202.202.68.201的ftp服务器上面,中间是
通过代理服务器实现转发的功能。


具体代码如下,现在能实现识别用户名和密码,但是在cuteftp上一直提示“数据socket建立失败”,请各位高人指点,这个代码该怎么修改和添加
才能实现ftp功能。在此先感谢了。


#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <fcntl.h>


#define TCP_PROTO "tcp"


int proxy_port; /* port to listen for proxy connections on */
struct sockaddr_in hostaddr; /* remote computer's address */


extern int errno; /* defined by libc.a */
/*extern char *sys_errlist[];*/


void parse_args (int argc, char **argv);
void daemonize (int servfd);
void do_proxy (int usersockfd);
void reap_status (void);
void errorout (char *msg);


/
***************************************************************************&shy;*
function: main
description: Main level driver. After daemonizing the process, a
socket
is opened to listen for connections on the proxy port,
connections are accepted and children are spawned to handle
each new connection.
arguments:
argc,argv you know what those are.


return value: none.
calls: parse_args, do_proxy.
globals: reads proxy_port.
***************************************************************************&shy;*/


main (argc,argv)
int argc;
char **argv;
{
   int clilen;
   int childpid;
   int sockfd, newsockfd;
   struct sockaddr_in servaddr, cliaddr;


   parse_args(argc,argv);


   /* prepare an address struct to listen for connections */
   bzero((char *) &servaddr, sizeof(servaddr));
   servaddr.sin_family = AF_INET;
   servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
   servaddr.sin_port = proxy_port;


   /* get a socket... */
   if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
      fputs("failed to create server socket",stderr);
      exit(1);
   }


   printf("Create socket successful!\n");


   /* ...and bind our address and port to it */
   if (bind(sockfd,(struct sockaddr *) (&servaddr),sizeof(servaddr))
< 0) {
      fputs("faild to bind server socket to specified port",stderr);
      exit(1);
   }
   printf("Bind host succeed!\n");


   /* get ready to accept with at most 5 clients waiting to connect
*/
   listen(sockfd,5);


   printf("listening \n");


   /* turn ourselves into a daemon */


   daemonize(sockfd);


   /* fall into a loop to accept new connections and spawn children
*/
   while (1) {


          /* accept the next connection */
          clilen = sizeof(struct sockaddr_in);
          newsockfd = accept(sockfd, (struct sockaddr *) (&cliaddr),
&clilen);


          printf("Create new connection!\n");


          if (newsockfd < 0 && errno == EINTR)
            continue; /* a signal might interrupt our accept() call */
          else if (newsockfd < 0)
          /* something quite amiss -- kill the server */
          errorout("failed to accept connection");


          /* fork a child to handle this connection */
          if ((childpid = fork()) == 0) {
         close(sockfd);
         do_proxy(newsockfd);
         exit(0);
          }


          /* if fork() failed, the connection is silently dropped --
oops! */


          close(newsockfd);
   }



}


/
***************************************************************************&shy;*
function: parse_args
description: parse the command line args.
arguments:
argc,argv you know what these are.

return value: none.
calls: none.
globals: writes proxy_port, writes hostaddr.
***************************************************************************&shy;*/


void parse_args (argc,argv)
int argc;
char **argv;
{
   int i;
   struct hostent *hostp;
   struct servent *servp;
   unsigned long inaddr;
   struct {
      char proxy_port ;
      char isolated_host ;
      char service_name ;
   } pargs;


    /*input is abnormal*/
   if (argc < 4) {
      printf("usage: %s <proxy-port> <remote host> <server-name|port-
number>\r\n",argv);
      exit(1);
   }


   strcpy(pargs.proxy_port,argv);
   strcpy(pargs.isolated_host,argv);
   strcpy(pargs.service_name,argv);


   for (i = 0; i < strlen(pargs.proxy_port); i++)
   if (!isdigit(*(pargs.proxy_port + i))) break;


   if (i == strlen(pargs.proxy_port))
          proxy_port = htons(atoi(pargs.proxy_port));
   else {
          printf("%s: invalid proxy port",pargs.proxy_port);
          exit(0);
   }


   bzero(&hostaddr,sizeof(hostaddr));
   hostaddr.sin_family = AF_INET;
   if ((inaddr = inet_addr(pargs.isolated_host)) != INADDR_NONE)
          bcopy(&inaddr,&hostaddr.sin_addr,sizeof(inaddr));
   else if ((hostp = gethostbyname(pargs.isolated_host)) != NULL)
          bcopy(hostp->h_addr,&hostaddr.sin_addr,hostp->h_length);
   else {
          printf("%s: unknown host",pargs.isolated_host);
          exit(1);
   }


   if ((servp = getservbyname(pargs.service_name,TCP_PROTO)) !=
NULL)
          hostaddr.sin_port = servp->s_port;
   else if (atoi(pargs.service_name) > 0)
          hostaddr.sin_port = htons(atoi(pargs.service_name));
   else {
          printf("%s: invalid/unknown service name or port
number",pargs.service_name);
          exit(1);
   }



}


/
***************************************************************************&shy;*
function: daemonize
description: detach the server process from the current context,
creating a pristine, predictable environment in which it
will execute.
arguments:
servfd file descriptor in use by server.

return value: none.
calls: none.
globals: none.
***************************************************************************&shy;*/


void daemonize (servfd)
int servfd;
{
   int childpid, fd, fdtablesize;


   /* ignore terminal I/O, stop signals */
   signal(SIGTTOU,SIG_IGN);
   signal(SIGTTIN,SIG_IGN);
   signal(SIGTSTP,SIG_IGN);


   /* fork to put us in the background (whether or not the user
   specified '&' on the command line */


   if ((childpid = fork()) < 0) {
      fputs("failed to fork first child",stderr);
      exit(1);
   }
   else if (childpid > 0)
      exit(0); /* terminate parent, continue in child */


   setsid();


   /* dissociate from process group */
   /*
   if (setpgrp(0,getpid()) < 0) {
      fputs("failed to become process group leader",stderr);
      exit(1);
   }
   */


   /* lose controlling terminal */
   if ((fd = open("/dev/tty",O_RDWR)) >= 0) {
      ioctl(fd,TIOCNOTTY,NULL);
      close(fd);
   }


   /* close any open file descriptors */
   for (fd = 0, fdtablesize = getdtablesize(); fd < fdtablesize; fd+
+)
   if (fd != servfd) close(fd);


   /* set working directory to / to allow filesystems to be
unmounted */
   chdir("/");


   /* clear the inherited umask */
   umask(0);


   /* setup zombie prevention */
   /*
   signal(SIGCLD,reap_status);
    */



}


/
***************************************************************************&shy;*
function: do_proxy
description: does the actual work of virtually connecting a client to
the telnet service on the isolated host.
arguments:
usersockfd socket to which the client is connected.

return value: none.
calls: none.
globals: reads hostaddr.
***************************************************************************&shy;*/


void do_proxy (usersockfd)
int usersockfd;
{
   int isosockfd;
   fd_set rdfdset;
   int connstat;
   int iolen;
   char buf ;


   /* open a socket to connect to the isolated host */
   if ((isosockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
      errorout("failed to create socket to host");


   printf("Succeed in creating new socket!\n");
   /* attempt a connection */
   connstat = connect(isosockfd,(struct sockaddr *)
&hostaddr,sizeof(hostaddr));
   printf("Attempt a connection.\n");


   switch (connstat) {
      case 0:
       break;
      case ETIMEDOUT:
      case ECONNREFUSED:
      case ENETUNREACH:
          strcpy(buf,strerror(errno)); /* sys_errlist outdated, we use
use strerror function now.added by liaoy*/
          strcat(buf,"\r\n");
          write(usersockfd,buf,strlen(buf));
          close(usersockfd);
          exit(1); /* die peacefully if we can't establish a connection
*/
      break;
   default:
      errorout("failed to connect to host");
}


   /* now we're connected, serve fall into the data echo loop */
   while (1) {
   /* Select for readability on either of our two sockets */
      FD_ZERO(&rdfdset);
      FD_SET(usersockfd,&rdfdset);
      FD_SET(isosockfd,&rdfdset);
      if (select(FD_SETSIZE,&rdfdset,NULL,NULL,NULL) < 0)
       errorout("select failed");


      /* is the client sending data? */
      if (FD_ISSET(usersockfd,&rdfdset)) {
       if ((iolen = recv(usersockfd,buf,sizeof(buf),0)) <= 0)
       break; /* zero length means the client disconnected */


       send(isosockfd,buf,iolen,0);
       printf("Client sends data :%s",buf);
      }


      /* is the host sending data? */
      if (FD_ISSET(isosockfd,&rdfdset)) {
       if ((iolen = recv(isosockfd,buf,sizeof(buf),0))<= 0)
       break; /* zero length means the host disconnected */


       send(usersockfd,buf,iolen,0);
       printf("Host sends data: %s",buf);
      }
   }


   /* we're done with the sockets */
   close(isosockfd);
   close(usersockfd);



}


/
***************************************************************************&shy;*
function: errorout
description: displays an error message on the console and kills the
current process.
arguments:
msg message to be displayed.

return value: none -- does not return.
calls: none.
globals: none.
***************************************************************************&shy;*/


void errorout (msg)
char *msg;
{
   FILE *console;


   console = fopen("/dev/console","a");
   fprintf(console,"proxyd: %s",msg);
   fclose(console);
   exit(1);



}


/
***************************************************************************&shy;*
function: reap_status
description: handle a SIGCLD signal by reaping the exit status of the
perished child, and discarding it.
arguments: none.
return value: none.
calls: none.
globals: none.
***************************************************************************&shy;*/

void reap_status ()
{
   int pid;
   union wait status;


   while ((pid = wait3(&status,WNOHANG,NULL)) > 0); /* loop while
there are more dead children */

liaoy_jackie 发表于 2008-10-21 08:31

请高人指点,谢谢

brianchen829 发表于 2013-06-06 18:45

我也遇到类似的问题,客户端连到代理提示是失败的,但服务器端已经收到请求了。不知你的问题解决了没有,能否分享下。
页: [1]
查看完整版本: 代理tcp服务器如何实现ftp功能?