代理tcp伺服器如何實現ftp功能?

←手機掃碼閱讀     火星人 @ 2014-03-04 , reply:0

代理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 */
《解決方案》

請高人指點,謝謝
《解決方案》

我也遇到類似的問題,客戶端連到代理提示是失敗的,但伺服器端已經收到請求了。不知你的問題解決了沒有,能否分享下。




[火星人 ] 代理tcp伺服器如何實現ftp功能?已經有454次圍觀

http://coctec.com/docs/service/show-post-11422.html